package org.jsola.hr.service.impl;

import cn.hutool.core.date.StopWatch;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jsola.admin.entity.HeaderFieldsDO;
import org.jsola.admin.vo.HeaderFieldsListVO;
import org.jsola.admin.vo.HeaderFieldsVO;
import org.jsola.admin.vo.SiteVO;
import org.jsola.common.PageKit;
import org.jsola.common.TreeKit;
import org.jsola.core.Page;
import org.jsola.core.entity.BaseDO;
import org.jsola.core.entity.BaseTreeDO;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.*;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.constant.SalaryConstants;
import org.jsola.hr.dao.IChildCompanyDAO;
import org.jsola.hr.dao.IGroupCompanyDAO;
import org.jsola.hr.dto.ChildCompanyAddDTO;
import org.jsola.hr.dto.ChildCompanyUpdateDTO;
import org.jsola.hr.dto.TypeAndId;
import org.jsola.hr.entity.*;
import org.jsola.hr.provider.*;
import org.jsola.hr.query.ChildCompanyQuery;
import org.jsola.hr.query.HrEmployeeSalaryNewQuery;
import org.jsola.hr.query.HrEmployeeSalaryQuery;
import org.jsola.hr.query.HrMonthlySalaryQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.vo.*;
import org.jsola.salary.entity.*;
import org.jsola.salary.vo.*;
import org.jsola.user.core.TokenUser;
import org.jsola.user.entity.UserDO;
import org.jsola.user.vo.UserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static org.jsola.salary.constant.CustomerDetailsType.SALARY;
import static org.jsola.salary.constant.CustomerDetailsType.SOCIAL;
import static org.jsola.salary.constant.HeaderType.CUSTOMER;

/**
 * 用工单位分组
 *
 * @author zhr
 */
@Slf4j
@Service("hrChildCompanyServiceImpl")
public class ChildCompanyServiceImpl implements IChildCompanyService {

    @Autowired
    private IChildCompanyDAO childCompanyDAO;

    @Autowired
    private IPermissionGroupProviderService groupProviderService;

    @Autowired
    private ICompanyService companyService;

    @Autowired
    private IGroupCompanyService groupCompanyService;

    @Autowired
    private IHrPermissionService hrPermissionService;

    @Autowired
    private IUserRoleCompanyService userRoleCompanyService;

    @Autowired
    private IPermissionProviderService permissionProviderService;

    @Autowired
    private ISalaryProviderService salaryProviderService;

    @Autowired
    private IHrCustomerDetailsService hrCustomerDetailsService;

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IAdminProviderService adminProviderService;

    @Autowired
    private IChildCompanyService childCompanyService;

    @Autowired
    private ISiteProviderService siteProviderService;

    @Autowired
    private IGroupCompanyDAO groupCompanyDAO;

    @Autowired
    private ICompanyCustomGroupingService companyCustomGroupingService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public ChildCompanyVO save(ChildCompanyAddDTO childCompanyAddDTO, TokenUser tokenUser) {
        // 转DO
        ChildCompanyDO childCompanyDO = childCompanyAddDTO.to(ChildCompanyDO.class);

        // 校验分公司名称
        checkChildCompanyName("", childCompanyDO.getName(), tokenUser.getSiteId());

        // 保存
        childCompanyDO = save(childCompanyDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return childCompanyDO.to(ChildCompanyVO.class);
    }

    /**
     * 校验分公司名称
     *
     * @param id     当前分公司id
     * @param name   分公司名称
     * @param siteId 站点
     */
    private void checkChildCompanyName(String id, String name, String siteId) {
        if (StringUtils.isEmpty(name)) {
            return;
        }
        Example example = new Example(ChildCompanyDO.class);
        example.and()
                .andEqualTo("name", name)
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (StringUtils.isNotEmpty(id)) {
            example.and().andNotEqualTo("id", id);
        }
        List<ChildCompanyDO> childCompanyList = childCompanyDAO.selectByExample(example);
        if (!CollectionUtils.isEmpty(childCompanyList)) {
            throw new ParamException("已存在名称为'" + name + "'的分公司,请修改");
        }
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public ChildCompanyVO saveChildCompanyAndRelation(ChildCompanyAddDTO childCompanyAddDTO, TokenUser tokenUser) {
        // 保存
        ChildCompanyVO childCompanySave = save(childCompanyAddDTO, tokenUser);

        // 同步到权限组
        groupProviderService.saveGroupByChildCompany(childCompanyAddDTO, childCompanySave.getId(), tokenUser);

        return selectById(childCompanySave.getId(), tokenUser.getSiteId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(ChildCompanyUpdateDTO childCompanyUpdateDTO, TokenUser tokenUser) {
        //转DO
        ChildCompanyDO childCompanyDO = childCompanyUpdateDTO.to(ChildCompanyDO.class);

        // 校验分公司名称
        checkChildCompanyName(childCompanyDO.getId(), childCompanyDO.getName(), tokenUser.getSiteId());

        //根据主键更新，只更新非null值
        return updateByIdSelective(childCompanyDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int updateChildCompanyAndRelation(ChildCompanyUpdateDTO childCompanyUpdateDTO, TokenUser tokenUser) {
        ChildCompanyDO childCompanyOld = selectDOById(childCompanyUpdateDTO.getId(), tokenUser.getSiteId());
        ParamException.notNull(childCompanyOld, "子公司不存在或已删除");

        //父分组不能是自己，以及自己的子分组
        List<String> groupIds = new ArrayList<>();
        groupIds.add(childCompanyUpdateDTO.getId());
        List<String> childGroupIds = groupTreeIds(groupIds, tokenUser.getSiteId());
        if (!CollectionUtils.isEmpty(childGroupIds)) {
            groupIds.addAll(childGroupIds);
        }

        if (groupIds.contains(childCompanyUpdateDTO.getParentId())) {
            throw new ParamException("上级分组不能是当前分组或当前分组的子分组");
        }

        groupProviderService.updateGroupByChildCompany(childCompanyUpdateDTO, childCompanyUpdateDTO.getId(), tokenUser);

        //根据主键更新，只更新非null值
        return update(childCompanyUpdateDTO, tokenUser);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... childCompanyIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) childCompanyIds);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteChildCompanyAndRelation(String childCompanyId, TokenUser tokenUser) {
        ChildCompanyDO childCompanyOld = selectDOById(childCompanyId, tokenUser.getSiteId());
        ParamException.notNull(childCompanyOld, "子公司不存在或已删除");

        //根据租ID查询整个分组树，然后进行删除
        List<String> pGroupId = new ArrayList<>();
        pGroupId.add(childCompanyId);
        List<String> list = groupTreeIds(pGroupId, tokenUser.getSiteId());

        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
            list.add(childCompanyId);
        } else {
            list.add(childCompanyId);
        }

        for (String groupId : list) {
            // 删除组相关,组/用户/分管城市/分管单位
            groupProviderService.deleteChildCompany(groupId, tokenUser);
        }

        return this.deleteByIds(tokenUser, list.toArray(new String[0]));
    }


    @Override
    public ChildCompanyVO selectById(String childCompanyId, String siteId) {
        ChildCompanyDO childCompanyDO = selectDOById(childCompanyId, siteId);
        if (childCompanyDO == null) {
            return null;
        }
        return childCompanyDO.to(ChildCompanyVO.class);
    }

    @Override
    public ChildCompanyDO selectDOByIdNotSite(String childCompanyId) {
        Example example = new Example(ChildCompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("id", childCompanyId);
        return childCompanyDAO.selectOneByExample(example);
    }


    @Override
    public ChildCompanyVO selectChildCompanyAndRelationById(String childCompanyId, String siteId) {
        ChildCompanyVO childCompany = selectById(childCompanyId, siteId);
        ParamException.notNull(childCompany, "子公司不存在或已删除");
        // 获取子公司关联信息
        return groupProviderService.findChildCompanyById(childCompany, siteId);
    }

    @Override
    public List<ChildCompanyListVO> select(ChildCompanyQuery childCompanyQuery, TokenUser tokenUser) {
        // 查询名称为空 返回有权限的所有用工单位及分组
        List<ChildCompanyListVO> childCompanyListVOList = selectTreeByUserId(tokenUser.getUserId(), tokenUser.getSiteId());

        if (CollectionUtils.isEmpty(childCompanyListVOList)) {
            return new ArrayList<>();
        }
        if (StringUtils.isBlank(childCompanyQuery.getName())) {
            if ("site".equals(childCompanyListVOList.get(0).getType())) {
                for (ChildCompanyListVO childCompanyListVO : childCompanyListVOList.get(0).getCompanyList()) {
                    if ("group".equals(childCompanyListVO.getType())) {
                        List<ChildCompanyListVO> companyList = childCompanyListVO.getCompanyList();
                        for (ChildCompanyListVO companyListVO : companyList) {
                            companyListVO.setUuid(childCompanyListVO.getId() + "-" + companyListVO.getId());
                        }
                    }
                    childCompanyListVO.setUuid(childCompanyListVO.getId());
                }
            }
            return childCompanyListVOList;
        }
        // 若首层为站点层 取下一层
        if ("site".equals(childCompanyListVOList.get(0).getType())) {
            childCompanyListVOList = childCompanyListVOList.get(0).getCompanyList();
            for (ChildCompanyListVO childCompanyListVO : childCompanyListVOList) {
                if ("group".equals(childCompanyListVO.getType())) {
                    List<ChildCompanyListVO> companyList = childCompanyListVO.getCompanyList();
                    for (ChildCompanyListVO companyListVO : companyList) {
                        companyListVO.setUuid(childCompanyListVO.getId() + "-" + companyListVO.getId());
                    }
                }
                childCompanyListVO.setUuid(childCompanyListVO.getId());
            }
        }

        if (StringUtils.isBlank(childCompanyQuery.getName())) {
            return childCompanyListVOList;
        }

        // 过滤匹配名称的用工单位及分组
        return filterName(childCompanyListVOList, childCompanyQuery.getName());
    }

    private List<ChildCompanyListVO> filterName(List<ChildCompanyListVO> childCompanyListVOList, String name) {
        List<ChildCompanyListVO> result = new ArrayList<>();
        for (ChildCompanyListVO childCompanyListVO : childCompanyListVOList) {
            List<ChildCompanyListVO> child = childCompanyListVO.getCompanyList();
            if (!CollectionUtils.isEmpty(child)) {
                List<ChildCompanyListVO> temp = filterName(child, name);
                if (!CollectionUtils.isEmpty(temp)) {
                    childCompanyListVO.setCompanyList(temp);
                    result.add(childCompanyListVO);
                }
            } else {
                if ("company".equals(childCompanyListVO.getType())) {
                    if (childCompanyListVO.getName().contains(name)) {
                        result.add(childCompanyListVO);
                    }
                } else {
                    List<ChildCompanyListVO> companyList = childCompanyListVO.getCompanyList();
                    if (CollectionUtils.isEmpty(companyList)) {
                        continue;
                    }
                    // 分组中含名称有全部返回
                    if (!childCompanyListVO.getName().contains(name)) {
                        companyList = companyList.parallelStream().filter(companyVO
                                -> companyVO.getName().contains(name)).collect(Collectors.toList());
                    }
                    if (CollectionUtils.isEmpty(companyList)) {
                        continue;
                    }
                    childCompanyListVO.setCompanyList(companyList);
                    result.add(childCompanyListVO);
                }
            }
        }
        return result;
    }

    @Override
    public List<ChildCompanyListVO> selectList(ChildCompanyQuery childCompanyQuery, TokenUser tokenUser) {
        List<ChildCompanyListVO> childCompanyListVOList = this.select(childCompanyQuery, tokenUser);
        List<ChildCompanyListVO> returnChildCompanyListVO = new ArrayList<>();
        if (CollectionUtils.isEmpty(childCompanyListVOList)) {
            return returnChildCompanyListVO;
        }
        for (ChildCompanyListVO childCompanyListVO : childCompanyListVOList) {
            buildCompanyList(returnChildCompanyListVO, childCompanyListVO);
        }
        // 过滤重复的companyId
        if (!CollectionUtils.isEmpty(returnChildCompanyListVO)) {
            returnChildCompanyListVO = returnChildCompanyListVO.stream().filter(
                    distinctByKey(ChildCompanyListVO::getId)).collect(Collectors.toList());
        }
        return returnChildCompanyListVO;
    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    private void buildCompanyList(List<ChildCompanyListVO> returnChildCompanyListVO,
                                  ChildCompanyListVO childCompanyListVO) {
        if ("company".equals(childCompanyListVO.getType())) {
            returnChildCompanyListVO.add(childCompanyListVO);
            return;
        }
        if (!CollectionUtils.isEmpty(childCompanyListVO.getCompanyList())) {
            for (ChildCompanyListVO companyListVO : childCompanyListVO.getCompanyList()) {
                buildCompanyList(returnChildCompanyListVO, companyListVO);
            }
        }

    }

    @Override
    public List<ChildCompanyListVO> selectTreeByUserId(String userId, String siteId) {
        StopWatch stopWatch = new StopWatch("selectTreeByUserId");

        // 查询公司下完整的用工单位树形结构
        stopWatch.start("selectAllTreeCompany");
        List<ChildCompanyListVO> childCompanyListVOList = selectAllTreeCompany(siteId);
        stopWatch.stop();

        //过滤当前登录人，有权限的用工单位分组和用工单位
        stopWatch.start("selectByUserId");
        UserCompanyVO userCompanyVO = selectByUserId(userId, siteId);
        stopWatch.stop();

        //过滤当前登录人的权限(能看到的权限，能编辑的权限)
        stopWatch.start("filterPermission");
        childCompanyListVOList = filterPermission(childCompanyListVOList, userCompanyVO, siteId);
        stopWatch.stop();
        log.info(stopWatch.prettyPrint());

        // 最外层放入总公司(站点)
        ChildCompanyListVO childCompanyListVO = new ChildCompanyListVO();
        String siteName = permissionProviderService.getSiteName(siteId);
        childCompanyListVO.setName(siteName);
        childCompanyListVO.setType("site");
        childCompanyListVO.setCompanyList(childCompanyListVOList);
        childCompanyListVO.setId("0");
        childCompanyListVO.setHasPermission(false);
        childCompanyListVO.setEdit(false);
        return Collections.singletonList(childCompanyListVO);
    }

    private List<ChildCompanyListVO> filterPermission(List<ChildCompanyListVO> childCompanyListVOList,
                                                      UserCompanyVO userCompanyVO,
                                                      String siteId) {

        if (userCompanyVO.getIsAllChildCompany()) {
            //如果全部，直接返回不用过滤
            return addEditStatus(childCompanyListVOList);
        } else {
            StopWatch stopWatch = new StopWatch("filterPermission");
            stopWatch.start("selectAllTreeCompany");

            //租户的全部分组
            List<ChildCompanyDO> list = selectBySiteId(siteId);
            list = TreeKit.toTreeList(list);

            //有权限的用工单位集合
            List<String> companyIds = userCompanyVO.getCompanyIds();
            //根据用工单位，反查上级所有分组（一直向上找到根节点）
            List<GroupCompanyDO> pGroup = groupCompanyService.selectByCompanyIds(companyIds, siteId);
            List<String> companyGroupId = pGroup.stream().map(GroupCompanyDO::getGroupId).collect(Collectors.toList());
            companyGroupId = findPIds(list, companyGroupId);

            //有权限的分组集合
            List<String> editGroupIds = userCompanyVO.getAllGroupIds();
            List<String> groupIds = userCompanyVO.getGroupIds();

            //根据父分组查询子分组集合
            if (!CollectionUtils.isEmpty(groupIds)) {
                List<ChildCompanyDO> childCompanyTreee = childCompanyDAO.groupTreeIds(groupIds, siteId);
                childCompanyTreee = ListKit.treeToList(childCompanyTreee);
                groupIds = childCompanyTreee.stream().map(ChildCompanyDO::getId).collect(Collectors.toList());//分组的所有下级分组

                //分组下的所有用工单位
                List<GroupCompanyDO> childCompany = groupCompanyService.selectByGroupIds(groupIds, siteId);
                List<String> childCompanyIds = childCompany.stream().map(GroupCompanyDO::getCompanyId).collect(Collectors.toList());
                companyIds.addAll(childCompanyIds);
            }

            //查询分组的所有上级分组
            List<String> groupPIds = findPIds(list, groupIds);//分组的上级分组
            stopWatch.stop();

            groupIds.addAll(companyGroupId);//用工单位的所有上级分组
            groupIds.addAll(groupPIds);//分组的所有上级分组
            groupIds.addAll(companyIds);


            //更新分组树，哪个分支有权限
            stopWatch.start("setPermission");
            setPermission(childCompanyListVOList, groupIds, editGroupIds);
            stopWatch.stop();

            //过滤分组树，排除没有权限的分支
            stopWatch.start("filterByPermission");
            filterByPermission(childCompanyListVOList);
            stopWatch.stop();

            log.info(stopWatch.prettyPrint());
        }
        return childCompanyListVOList;
    }

    private List<ChildCompanyListVO> addEditStatus(List<ChildCompanyListVO> childCompanyListVOList) {
        for (int i = 0; i < childCompanyListVOList.size(); i++) {
            ChildCompanyListVO childCompanyListVO = childCompanyListVOList.get(i);
            List<ChildCompanyListVO> child = childCompanyListVO.getCompanyList();
            if (!CollectionUtils.isEmpty(child)) {
                addEditStatus(child);
            }
            childCompanyListVO.setEdit(true);
        }
        return childCompanyListVOList;
    }

    /**
     * 根据组id,查询所有的上级分组
     *
     * @return
     */
    private List<String> findPIds(List<ChildCompanyDO> list, List<String> groupIds) {
        List<String> result = groupIds;
        for (ChildCompanyDO childCompanyDO : list) {
            if (!CollectionUtils.isEmpty(childCompanyDO.getChildList())) {
                List<ChildCompanyDO> childList = new ArrayList<>();
                List<BaseTreeDO> baseTree = childCompanyDO.getChildList();
                for (BaseTreeDO baseTreeDO : baseTree) {
                    ChildCompanyDO child = (ChildCompanyDO) baseTreeDO;
                    childList.add(child);
                }
//                result.addAll(findPIds(childList, groupIds));
                findPIds(childList, groupIds);
            }
            if (groupIds.contains(childCompanyDO.getId())) {
                String pId = (String) childCompanyDO.getParentId();
                if (!pId.equals("0") && !groupIds.contains(pId) && !result.contains(pId)) {
                    result.add(pId);
                }
            }
        }
        return result;
    }

    /**
     * childCompanyListVOList树，包含groupIds，就更新权限状态字段
     *
     * @param childCompanyListVOList
     * @param groupIds               所有能看见的分组
     * @param editGroupIds           拥有权限的分组（能编辑）
     */
    private void setPermission(List<ChildCompanyListVO> childCompanyListVOList,
                               List<String> groupIds,
                               List<String> editGroupIds) {
        //更新分组树，哪个分支有权限
        for (ChildCompanyListVO childCompanyListVO : childCompanyListVOList) {
            String id = childCompanyListVO.getId();
            if (groupIds.contains(id)) {
                childCompanyListVO.setHasPermission(true);
            }
            if (editGroupIds.contains(id)) {
                childCompanyListVO.setEdit(true);
            }
            if (!CollectionUtils.isEmpty(childCompanyListVO.getCompanyList())) {
                setPermission(childCompanyListVO.getCompanyList(), groupIds, editGroupIds);
            }
        }
    }

    /**
     * 递归childCompanyListVOList，把hasPermission=false的删除
     *
     * @param childCompanyListVOList
     */
    private void filterByPermission(List<ChildCompanyListVO> childCompanyListVOList) {
        Iterator<ChildCompanyListVO> itr = childCompanyListVOList.iterator();
        while (itr.hasNext()) {
            ChildCompanyListVO childCompanyListVO = itr.next();
            if (childCompanyListVO.getHasPermission() == null || !childCompanyListVO.getHasPermission()) {
                itr.remove();
            } else {
                if (!CollectionUtils.isEmpty(childCompanyListVO.getCompanyList())) {
                    filterByPermission(childCompanyListVO.getCompanyList());
                }
            }
        }
    }

    @Override
    public UserCompanyVO selectByUserId(String userId, String siteId) {
        ParamException.notNull(userId, "未选择要查询的用户");
        UserCompanyVO userCompanyVO = new UserCompanyVO();
        // 公司下用工单位权限
        List<UserRoleCompanyDO> userRoleCompanyDOList = userRoleCompanyService.selectByUserId(userId, siteId);
        // 未创建公司角色 但是管理员 有总公司权限
        if (CollectionUtils.isEmpty(userRoleCompanyDOList) && hrPermissionService.isAdmin(userId, siteId)) {
            // 管理员有所有用工单位分组及用工单位权限
            userCompanyVO.setIsAllChildCompany(true);
            return userCompanyVO;
        }
        // 是否有总公司权限
        if (userRoleCompanyDOList.parallelStream().anyMatch(UserRoleCompanyDO::getIsAllChildCompany)) {
            userCompanyVO.setIsAllChildCompany(true);
            return userCompanyVO;
        }
        List<String> groupIds = new ArrayList<>();
        List<String> companyIds = new ArrayList<>();
        for (UserRoleCompanyDO userRoleCompanyDO : userRoleCompanyDOList) {
            if (userRoleCompanyDO.getIsAllEmployer()) {
                //放入组id
                groupIds.add(userRoleCompanyDO.getChildCompanyId());
            } else {
                //放入用工单位id
                companyIds.add(userRoleCompanyDO.getEmployerId());
            }
        }
        userCompanyVO.setIsAllChildCompany(false);
        userCompanyVO.setGroupIds(groupIds);
        userCompanyVO.setCompanyIds(companyIds);
        List<ChildCompanyDO> treeList = groupTree(groupIds, siteId);
        //有权限的分组
        userCompanyVO.setTreeList(treeList);
        //groupIds 递归查询全部的组id
        treeList = ListKit.treeToList(treeList);
        userCompanyVO.setAllGroupIds(treeList.stream().map(ChildCompanyDO::getId).collect(Collectors.toList()));
        return userCompanyVO;
    }

    @Override
    public List<ChildCompanyListVO> selectAllTreeCompany(String siteId) {
        // 查询所有用工单位
        List<CompanyDO> allCompanyList = companyService.selectBySiteId(siteId);
        // 站点下没有用工单位 直接返回
        if (CollectionUtils.isEmpty(allCompanyList)) {
            return new ArrayList<>();
        }
        // id-用工单位
        Map<String, CompanyDO> idCompanyMap = allCompanyList.parallelStream().collect(Collectors.toMap(BaseDO::getId, v -> v));

        // 查询所有分组
        List<ChildCompanyDO> childCompanyDOList = selectChildCompanyListBySiteId(siteId);
        // 平铺转树
        List<ChildCompanyDO> childCompanyTree = TreeKit.toTreeList(childCompanyDOList);

        // 分组下用工单位
        List<GroupCompanyDO> groupCompanyDOList = groupCompanyService.selectByGroupIds(childCompanyDOList
                .parallelStream().map(BaseDO::getId).collect(Collectors.toList()), siteId);
        // groupId分组
        Map<String, List<GroupCompanyDO>> groupIdListMap = groupCompanyDOList.parallelStream()
                .collect(Collectors.groupingBy(GroupCompanyDO::getGroupId));

        //组装数据：递归 childCompanyTree下的 childList，赋值 companyList
        List<ChildCompanyListVO> childCompanyListVOList = combinate2(allCompanyList, idCompanyMap, groupIdListMap, childCompanyTree);

        // 没有分组的公司 加入到分组级显示
        boolean isAll = groupCompanyDOList.parallelStream().anyMatch(GroupCompanyDO::getIsAll);
        if (!isAll) {
            // 已有分组的用工单位
            List<String> companyIds = groupCompanyDOList.parallelStream().map(GroupCompanyDO::getCompanyId)
                    .distinct().collect(Collectors.toList());
            // 没有分组的用工单位
            List<ChildCompanyListVO> otherCompany = allCompanyList.parallelStream().map(companyDO -> {
                if (companyIds.contains(companyDO.getId())) {
                    return null;
                }
                ChildCompanyListVO companyListVO = companyDO.to(ChildCompanyListVO.class);
                companyListVO.setType("company");
                companyListVO.setUuid(UUID.randomUUID().toString().replace("-", ""));
                companyListVO.setParentId("0");
                return companyListVO;
            }).filter(Objects::nonNull).collect(Collectors.toList());
            childCompanyListVOList.addAll(otherCompany);
        }

        return childCompanyListVOList;
    }

    /**
     * 拼装用工单位分组、用工单位树形结构
     *
     * @param idCompanyMap     用工单位id:用工单位信息
     * @param groupIdListMap   用工单位分组id:分组下的用工单位
     * @param childCompanyTree 用工单位分组，树形结构
     * @return
     */
    private List<ChildCompanyListVO> combinate(List<CompanyDO> allCompanyList,
                                               Map<String, CompanyDO> idCompanyMap,
                                               Map<String, List<GroupCompanyDO>> groupIdListMap,
                                               List<ChildCompanyDO> childCompanyTree) {
        List<ChildCompanyListVO> list = new ArrayList<>();
        for (ChildCompanyDO childCompanyDO : childCompanyTree) {

            List<ChildCompanyListVO> companyList = new ArrayList<>();
            // 分组下用工单位
            List<GroupCompanyDO> groupCompanyList = groupIdListMap.get(childCompanyDO.getId());
            if (!CollectionUtils.isEmpty(groupCompanyList)) {
                for (GroupCompanyDO groupCompanyDO : groupCompanyList) {
                    if (groupCompanyDO.getIsAll()) {
                        companyList = allCompanyList.parallelStream().map(companyDO -> {
                            ChildCompanyListVO companyListVO = companyDO.to(ChildCompanyListVO.class);
                            companyListVO.setType("company");
                            companyListVO.setUuid(UUID.randomUUID().toString().replace("-", ""));

                            return companyListVO;
                        }).collect(Collectors.toList());
                        break;
                    }
                    CompanyDO companyDO = idCompanyMap.get(groupCompanyDO.getCompanyId());
                    if (companyDO != null) {
                        ChildCompanyListVO companyListVO = companyDO.to(ChildCompanyListVO.class);
                        companyListVO.setType("company");
                        companyListVO.setUuid(UUID.randomUUID().toString().replace("-", ""));
                        companyList.add(companyListVO);
                    }
                }
            }

            //分组下的分组
            List<ChildCompanyListVO> groupList = new ArrayList<>();
            if (childCompanyDO.getHasChild() != null && childCompanyDO.getHasChild()) {
                List<BaseTreeDO> childList = childCompanyDO.getChildList();
                for (BaseTreeDO baseTreeDO : childList) {
                    ChildCompanyListVO childCompanyListVO = baseTreeDO.to(ChildCompanyListVO.class);
                    childCompanyListVO.setType("group");
                    childCompanyListVO.setUuid(UUID.randomUUID().toString().replace("-", ""));
                    groupList.add(childCompanyListVO);
                }
            }

            companyList.addAll(groupList);
            Collections.sort(companyList);

            ChildCompanyListVO childCompanyListVO = childCompanyDO.to(ChildCompanyListVO.class);
            childCompanyListVO.setType("group");
            childCompanyListVO.setUuid(UUID.randomUUID().toString().replace("-", ""));
            childCompanyListVO.setCompanyList(companyList);
            list.add(childCompanyListVO);

        }
        return list;
    }

    private List<ChildCompanyListVO> combinate2(List<CompanyDO> allCompanyList,
                                                Map<String, CompanyDO> idCompanyMap,
                                                Map<String, List<GroupCompanyDO>> groupIdListMap,
                                                List<ChildCompanyDO> childCompanyTree) {
        List<ChildCompanyListVO> list = new ArrayList<>();
        for (ChildCompanyDO childCompanyDO : childCompanyTree) {

            List<ChildCompanyListVO> companyList = getChildCompanyListVOS(allCompanyList, idCompanyMap, groupIdListMap, childCompanyDO);

            ChildCompanyListVO childCompanyListVO = childCompanyDO.to(ChildCompanyListVO.class);
            childCompanyListVO.setType("group");
            childCompanyListVO.setUuid(UUID.randomUUID().toString().replace("-", ""));
            childCompanyListVO.setCompanyList(companyList);
            //给前端返回的数据少一些，childList没用
            childCompanyListVO.setChildList(null);
            list.add(childCompanyListVO);

        }
        return list;
    }

    @NotNull
    private List<ChildCompanyListVO> getChildCompanyListVOS(List<CompanyDO> allCompanyList,
                                                            Map<String, CompanyDO> idCompanyMap,
                                                            Map<String, List<GroupCompanyDO>> groupIdListMap,
                                                            ChildCompanyDO childCompanyDO) {
        List<ChildCompanyListVO> companyList = new ArrayList<>();
        // 分组下用工单位
        List<GroupCompanyDO> groupCompanyList = groupIdListMap.get(childCompanyDO.getId());
        if (!CollectionUtils.isEmpty(groupCompanyList)) {
            for (GroupCompanyDO groupCompanyDO : groupCompanyList) {
                if (groupCompanyDO.getIsAll()) {
                    companyList = allCompanyList.parallelStream().map(companyDO -> {
                        ChildCompanyListVO companyListVO = companyDO.to(ChildCompanyListVO.class);
                        companyListVO.setType("company");
                        companyListVO.setUuid(UUID.randomUUID().toString().replace("-", ""));
                        companyListVO.setParentId(groupCompanyDO.getCompanyId());
                        return companyListVO;
                    }).collect(Collectors.toList());
                    break;
                }
                CompanyDO companyDO = idCompanyMap.get(groupCompanyDO.getCompanyId());
                if (companyDO != null) {
                    ChildCompanyListVO companyListVO = companyDO.to(ChildCompanyListVO.class);
                    companyListVO.setType("company");
                    companyListVO.setUuid(UUID.randomUUID().toString().replace("-", ""));
                    companyListVO.setParentId(groupCompanyDO.getCompanyId());
                    companyList.add(companyListVO);
                }
            }
        }

        //分组下的分组
        List<ChildCompanyListVO> groupList = new ArrayList<>();
        if (childCompanyDO.getHasChild() != null && childCompanyDO.getHasChild()) {
            List<BaseTreeDO> childList = childCompanyDO.getChildList();
            for (BaseTreeDO baseTreeDO : childList) {
                ChildCompanyListVO childCompanyListVO = baseTreeDO.to(ChildCompanyListVO.class);
                ChildCompanyDO tempChildCompanyDO = baseTreeDO.to(ChildCompanyDO.class);
                childCompanyListVO.setType("group");
                childCompanyListVO.setUuid(UUID.randomUUID().toString().replace("-", ""));
                childCompanyListVO.setCompanyList(getChildCompanyListVOS(allCompanyList, idCompanyMap, groupIdListMap, tempChildCompanyDO));
                //给前端返回的数据少一些，childList没用
                childCompanyListVO.setChildList(null);
                groupList.add(childCompanyListVO);
            }
        }

        companyList.addAll(groupList);
        Collections.sort(companyList);
        return companyList;
    }


    @Override
    public List<ChildCompanyListVO> selectChildCompanyListByCompanyId(String companyId, String siteId) {
        List<ChildCompanyDO> childCompanyDOList = selectChildCompanyListBySiteId(siteId);
        List<ChildCompanyListVO> childCompanyList = getVoListByDoList(childCompanyDOList);
        if (!CollectionUtils.isEmpty(childCompanyList)) {
            // 添加子公司关联信息
            return addRelationToChildCompany(childCompanyList, siteId);
        }
        return childCompanyList;
    }

    private List<ChildCompanyDO> selectChildCompanyListBySiteId(String siteId) {
        Example example = new Example(ChildCompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        return childCompanyDAO.selectByExample(example);
    }

    /**
     * 添加子公司关联信息
     *
     * @param childCompanyList 子公司信息
     * @param siteId           站点
     * @return 子公司关联信息
     */
    @Override
    public List<ChildCompanyListVO> addRelationToChildCompany(List<ChildCompanyListVO> childCompanyList, String siteId) {
        if (CollectionUtils.isEmpty(childCompanyList)) {
            return null;
        }
        return childCompanyList.stream().map(
                childCompany -> {
                    ChildCompanyVO childCompanyVO = selectChildCompanyAndRelationById(childCompany.getId(), siteId);
                    return childCompanyVO.to(ChildCompanyListVO.class);
                }
        ).filter(Objects::nonNull).collect(Collectors.toList());
    }

    /**
     * 根据doList获取voList
     *
     * @param doList doList
     * @return voList
     */
    private List<ChildCompanyListVO> getVoListByDoList(List<ChildCompanyDO> doList) {
        if (CollectionUtils.isEmpty(doList)) {
            return doList == null ? null : new ArrayList<>();
        }
        return doList.stream()
                .map(childCompanyDO -> childCompanyDO.to(ChildCompanyListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(ChildCompanyQuery childCompanyQuery, String siteId) {
        Example example = buildExample(childCompanyQuery, siteId);
        return childCompanyDAO.selectCountByExample(example);
    }

    @Override
    public Page<ChildCompanyListVO> selectPage(ChildCompanyQuery childCompanyQuery, String siteId) {
        Example example = buildExample(childCompanyQuery, siteId);
        Page<ChildCompanyDO> page = childCompanyDAO.selectPageByExample(example,
                childCompanyQuery.getPageNo(),
                childCompanyQuery.getPageSize());
        if (CollectionUtils.isEmpty(page.getEntities())) {
            return page.to(ChildCompanyListVO.class);
        }
        // 添加关联信息
        Page<ChildCompanyListVO> pageVo = page.to(ChildCompanyListVO.class);
        List<ChildCompanyListVO> childCompanyList = addRelationToChildCompany(pageVo.getEntities(), siteId);
        pageVo.setEntities(childCompanyList);

        return pageVo;
    }

    @Override
    public ChildCompanyDO selectDOById(String childCompanyId, String siteId) {
        return listById(childCompanyId, siteId);
    }

    @Override
    public List<ChildCompanyDO> selectByIds(List<String> childCompanyIds, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(childCompanyIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(ChildCompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId())
                .andIn("id", childCompanyIds);
        return childCompanyDAO.selectByExample(example);
    }

    @Override
    public List<ChildCompanyDO> selectDO(ChildCompanyQuery childCompanyQuery, String siteId) {
        Example example = buildExample(childCompanyQuery, siteId);
        return childCompanyDAO.selectByExample(example);
    }

    @Override
    public List<ChildCompanyListVO> listByIdList(List<String> idList, String siteId) {
        if (CollectionUtils.isEmpty(idList)) {
            return null;
        }
        Example example = new Example(ChildCompanyDO.class);
        example.and()
                .andIn("id", idList)
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        return getVoListByDoList(childCompanyDAO.selectByExample(example));
    }

    @Override
    public List<ChildCompanyDO> selectBySiteId(String siteId) {
        Example example = new Example(ChildCompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        return childCompanyDAO.selectByExample(example);
    }


    /**
     * 客户明细表逻辑：
     * 1、查询所有分组  + 挂在租户下的用工单位，放在两个map里面，一个map放分组，一个map放用工单位
     * 2、循环分组，查询用工单位，把下面的用工单位放到map的用工单位下
     * 3、根据用工单位集合，查询客户明细表
     * 4、查询出的客户明细表，根据用工单位分组聚合（校验了一下，同一个用工单位、在同一个月份，不能生成多个客户明细表）
     * 5、构造两个map,分组map存id,name;用工单位map存id,name
     * 6、每个客户明细表，计算相关费用
     * 7、客户明细表，按照用工单位分组，组装成树
     * 8、相关金额聚合到根节点
     *
     * @param hrMonthlySalaryQuery 用工单位查询条件
     * @param tokenUser            当前用户
     * @return
     */
    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<HrMonthlySalarySummaryVO> selectMonthlySalaryByCompanyList(HrMonthlySalaryQuery hrMonthlySalaryQuery, TokenUser tokenUser) {

        // 过滤没有权限的公司
        UserCompanyVO userCompanyVO = selectByUserId(tokenUser.getUserId(), tokenUser.getSiteId());

        List<TypeAndId> typeAndIdList = new ArrayList<>();
        TypeAndId type = hrMonthlySalaryQuery.getType();
        if (type != null && StringUtils.isNotBlank(type.getId())) {
            typeAndIdList = calcTypeAndIdList(type, userCompanyVO, tokenUser.getSiteId());
        } else {
            // 类型和Id
            typeAndIdList = hrMonthlySalaryQuery.getTypeAndIdList();
        }

        if (CollectionUtils.isEmpty(typeAndIdList)) {
            return new ArrayList<>();
        }
        // 类型为公司的Id
        List<String> companyIds = typeAndIdList.parallelStream().filter(typeAndId -> "company"
                .equals(typeAndId.getType())).map(TypeAndId::getId).collect(Collectors.toList());
        // 类型为分组的Id
        List<String> groupIds = typeAndIdList.parallelStream().filter(typeAndId -> "group"
                .equals(typeAndId.getType())).map(TypeAndId::getId).collect(Collectors.toList());

        // 分组下公司信息
        Map<String, List<GroupCompanyDO>> groupIdListMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(groupIds)) {
            //groupIds 已经是一个树了，不用再查了
//            groupIds = childCompanyService.groupTreeIds(groupIds, tokenUser.getSiteId());
            // 分组下的公司信息
            List<GroupCompanyDO> groupCompanyDOList = groupCompanyService.selectByGroupIds(groupIds, tokenUser.getSiteId());

            // 是否有全用工单位分组
            if (groupCompanyDOList.parallelStream().anyMatch(GroupCompanyDO::getIsAll)) {
                List<CompanyDO> companyDOList = companyService.selectBySiteId(tokenUser.getSiteId());
                companyIds = companyDOList.parallelStream().map(BaseDO::getId).collect(Collectors.toList());
            } else {
                List<String> companyIdList = groupCompanyDOList.parallelStream()
                        .map(GroupCompanyDO::getCompanyId).collect(Collectors.toList());
                companyIds.addAll(companyIdList);
                // 去重
                companyIds = companyIds.parallelStream().distinct().collect(Collectors.toList());
            }
            groupIdListMap = groupCompanyDOList.parallelStream()
                    .collect(Collectors.groupingBy(GroupCompanyDO::getGroupId));
        }
        // 公司下员工月工资统计
        Integer yearly = hrMonthlySalaryQuery.getYearly();
        Integer monthly = hrMonthlySalaryQuery.getMonthly();
        List<CustomerDetailsDO> customerDetailsDOList = salaryProviderService.selectCustomerDetailsByTypeAndCompanyIds(
                yearly, monthly, hrMonthlySalaryQuery.getCustomerDetailsType(), companyIds, tokenUser);
        if (CollectionUtils.isEmpty(customerDetailsDOList)) {
            return new ArrayList<>();
        }
        // 客户明细 按用工单位分组
        Map<String, List<CustomerDetailsDO>> companyIdListMap = customerDetailsDOList.parallelStream()
                .collect(Collectors.groupingBy(CustomerDetailsDO::getCompanyId));
        Map<String, CustomerDetailsDO> companyIdDoMap = new HashMap<>();
        for (String companyId : companyIdListMap.keySet()) {
            List<CustomerDetailsDO> customerDetailsList = companyIdListMap.get(companyId);
            String companyName = "";
            if (customerDetailsList.size() > 1) {
                CompanyVO companyVO = companyService.selectBaseCompanyById(companyId, tokenUser.getSiteId());
                if (companyVO != null) {
                    companyName = companyVO.getName();
                } else {
                    log.error("查询用工单位错误，companyId：{}, tokenUser：{}", companyId, tokenUser);
                }
                throw new ParamException("用工单位：" + companyName + "创建了多个客户明细信息，请联系系统管理员");
            }
            companyIdDoMap.put(companyId, customerDetailsList.get(0));
        }
        // 分组Id-name
        List<ChildCompanyDO> childCompanyDOList = selectByIds(groupIds, tokenUser);
        Map<String, String> groupIdNameMap = childCompanyDOList.parallelStream()
                .collect(Collectors.toMap(BaseDO::getId, ChildCompanyDO::getName));
        Map<String, String> groupIdPidMap = childCompanyDOList.parallelStream()
                .collect(Collectors.toMap(BaseDO::getId, ChildCompanyDO::getParentId));

        // 公司Id-name
        List<CompanyDO> companyDOList = companyService.selectByIds(companyIds, tokenUser.getSiteId());
        Map<String, String> companyIdNameMap = companyDOList.parallelStream()
                .collect(Collectors.toMap(BaseDO::getId, CompanyDO::getName));
        // 数据统计
        List<HrMonthlySalarySummaryVO> hrMonthlySalarySummaryVOList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(groupIds)) {
            for (String groupId : groupIds) {
                List<GroupCompanyDO> groupCompanyDOList = groupIdListMap.get(groupId);
                if (CollectionUtils.isEmpty(groupCompanyDOList)) {
                    continue;
                }
                // 是否有全用工单位分组
                boolean allCCompany = groupCompanyDOList.parallelStream().anyMatch(GroupCompanyDO::getIsAll);
                List<String> companyIdList;
                if (allCCompany) {
                    companyIdList = companyIds;
                } else {
                    companyIdList = groupCompanyDOList.parallelStream()
                            .map(GroupCompanyDO::getCompanyId).collect(Collectors.toList());
                }

                List<String> userCompanyIds = userCompanyVO.getCompanyIds();
                if (CollectionUtils.isEmpty(userCompanyIds)) {
                    userCompanyIds = groupCompanyService
                            .selectCompanyIdsByGroupIds(userCompanyVO.getGroupIds(), tokenUser.getSiteId());
                } else {
                    userCompanyIds.addAll(groupCompanyService
                            .selectCompanyIdsByGroupIds(userCompanyVO.getGroupIds(), tokenUser.getSiteId()));
                }
                List<HrMonthlySalarySummaryVO> companySummaryList = new ArrayList<>();
                // 分组下各公司
                for (String companyId : companyIdList) {
                    // 非全部用工单位权限 且 用工单位权限为空 或不包含此用工单位
                    if (!userCompanyVO.getIsAllChildCompany() && (CollectionUtils.isEmpty(userCompanyIds)
                            || !userCompanyIds.contains(companyId))) {
                        continue;
                    }
                    // 公司下的员工月工资
                    CustomerDetailsDO customerDetailsDO = companyIdDoMap.get(companyId);
                    if (customerDetailsDO == null) {
                        continue;
                    }
                    HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO = getHrSummaryVoByCompany(companyId
                            , companyIdNameMap.get(companyId), yearly, monthly, customerDetailsDO);
                    companySummaryList.add(hrMonthlySalarySummaryVO);
                }
                if (CollectionUtils.isEmpty(companySummaryList)) {
                    continue;
                }
                HrMonthlySalarySummaryVO hrSummaryVoByGroup = getHrSummaryVoByGroup(groupId
                        , groupIdNameMap.get(groupId), yearly, monthly, companySummaryList, groupIdPidMap);
                hrMonthlySalarySummaryVOList.add(hrSummaryVoByGroup);
            }
        }

        //把用工单位分组，组装成树(先找到根节点，然后一点点拼分支)
        //先查询分组树，再把客户明细表组装到树上
        ChildCompanyQuery childCompanyQuery = new ChildCompanyQuery();
        List<ChildCompanyListVO> groupTree = childCompanyService.select(childCompanyQuery, tokenUser);
        if (CollectionUtils.isEmpty(groupTree)) {
            return new ArrayList<>();
        }
        //第一层是用工单位，从第二层开始是分组
        groupTree = groupTree.get(0).getCompanyList();
        hrMonthlySalarySummaryVOList = monthlySalarySummaryToTree(hrMonthlySalarySummaryVOList, groupTree);

        for (TypeAndId typeAndId : typeAndIdList) {
            if ("group".equals(typeAndId.getType())) {

            } else if ("company".equals(typeAndId.getType())) {
                // 公司下的员工月工资
                CustomerDetailsDO customerDetailsDO = companyIdDoMap.get(typeAndId.getId());
                if (customerDetailsDO == null) {
                    continue;
                }
                HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO = getHrSummaryVoByCompany(typeAndId.getId()
                        , companyIdNameMap.get(typeAndId.getId()), yearly, monthly, customerDetailsDO);
                hrMonthlySalarySummaryVOList.add(hrMonthlySalarySummaryVO);
            }
        }

        //更新金额，数量等聚合数据
        for (HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO : hrMonthlySalarySummaryVOList) {
            calEmpNum(hrMonthlySalarySummaryVO);
        }

        return hrMonthlySalarySummaryVOList;
    }

    /**
     * 查询客户明细表新逻辑
     *
     * @param hrMonthlySalaryQuery
     * @param tokenUser
     * @return
     */
    public List<HrMonthlySalarySummaryVO> selectMonthlySalaryByCompanyList2(
            HrMonthlySalaryQuery hrMonthlySalaryQuery,
            TokenUser tokenUser) {
        // 数据统计
        List<HrMonthlySalarySummaryVO> hrMonthlySalarySummaryVOList = new ArrayList<>();

        //1、查询某个分组或者用工单位
        TypeAndId type = hrMonthlySalaryQuery.getType();

        //2、当前登录人权限
        UserCompanyVO userCompanyVO = selectByUserId(tokenUser.getUserId(), tokenUser.getSiteId());

        //3、过滤权限,返回有权限的分组和用工单位集合
        Map permissionMap = filterCustomerDetailCompanyIds(type, userCompanyVO, tokenUser.getSiteId());
        List<String> groupIds = (List<String>) permissionMap.get("group");
        List<String> companyIds = groupCompanyService.selectCompanyIdListByGroupIds(groupIds, tokenUser.getSiteId());

        //分组下的用工单位
        if (permissionMap.get("company") != null) {
            companyIds.addAll((List<String>) permissionMap.get("company"));
        }

        //分组下有权限的用工单位
        List<String> permissionCompanyIds = (List<String>) permissionMap.get("permissionGroupAndCompanyIds");


        //4、根据用工单位集合，查询客户明细表
        List<CustomerDetailsDO> customerDetailsDOList = salaryProviderService.selectCustomerDetailsByTypeAndCompanyIds(
                hrMonthlySalaryQuery.getYearly(), hrMonthlySalaryQuery.getMonthly(), hrMonthlySalaryQuery.getCustomerDetailsType(),
                permissionCompanyIds, tokenUser);

        //Map: 用工单位id: 客户明细表
        Map<String, List<CustomerDetailsDO>> companyIdCustomerDetailsMap = customerDetailsDOList.parallelStream()
                .collect(Collectors.groupingBy(CustomerDetailsDO::getCompanyId));

        // 公司Id-name
        List<CompanyDO> companyDOList = companyService.selectByIds(companyIds, tokenUser.getSiteId());
        Map<String, String> companyIdNameMap = companyDOList.parallelStream()
                .collect(Collectors.toMap(BaseDO::getId, CompanyDO::getName));
        List<ChildCompanyDO> childCompanyDOList = selectBySiteId(tokenUser.getSiteId());

        // 分组Id-name
        Map<String, String> groupIdNameMap = childCompanyDOList.parallelStream()
                .collect(Collectors.toMap(BaseDO::getId, ChildCompanyDO::getName));
        // 分组id-上级分组id
        Map<String, String> groupIdPidMap = childCompanyDOList.parallelStream()
                .collect(Collectors.toMap(BaseDO::getId, ChildCompanyDO::getParentId));

        //用工单位id 和 分组的对应关系
        List<GroupCompanyDO> groupCompanyDOList = groupCompanyService.selectByCompanyIds(companyIds, tokenUser.getSiteId());

        //companydId:分组Id集合
        Map<String, List<String>> companyIdGroupMap = new HashMap<>();
        for (GroupCompanyDO groupCompanyDO : groupCompanyDOList) {
            String groupId = groupCompanyDO.getGroupId();
            String companyId = groupCompanyDO.getCompanyId();
            List<String> companyForGroupId = companyIdGroupMap.get(companyId);
            if (CollectionUtils.isEmpty(companyForGroupId)) {
                companyForGroupId = new ArrayList<>();
                companyForGroupId.add(groupId);
            } else {
                companyForGroupId.add(groupId);
            }
            companyIdGroupMap.put(companyId, companyForGroupId);
        }

        //Map: 分组id: 客户明细表
        Map<String, List<CustomerDetailsDO>> groupIdCustomerDetailsMap = new HashMap<>();
        for (CustomerDetailsDO customerDetailsDO : customerDetailsDOList) {
            String companyId = customerDetailsDO.getCompanyId();
            List<String> customerDetailsGroupIds = companyIdGroupMap.get(companyId);
            if (CollectionUtils.isEmpty(customerDetailsGroupIds)) {
                //挂在租户下
                List<CustomerDetailsDO> list = groupIdCustomerDetailsMap.get("0");
                if (CollectionUtils.isEmpty(list)) {
                    list = new ArrayList<>();
                    list.add(customerDetailsDO);
                } else {
                    list.add(customerDetailsDO);
                }
                groupIdCustomerDetailsMap.put("0", list);
            } else {
                for (String groupId : customerDetailsGroupIds) {
                    List<CustomerDetailsDO> list = groupIdCustomerDetailsMap.get(groupId);
                    if (CollectionUtils.isEmpty(list)) {
                        list = new ArrayList<>();
                        list.add(customerDetailsDO);
                    } else {
                        list.add(customerDetailsDO);
                    }
                    groupIdCustomerDetailsMap.put(groupId, list);
                }
            }
        }

        //5、把客户明细表拼装成VO结构,挂在分组或者租户下
        List<HrMonthlySalarySummaryVO> voList = new ArrayList<>();
        for (String groupId : groupIdCustomerDetailsMap.keySet()) {
            List<CustomerDetailsDO> list = groupIdCustomerDetailsMap.get(groupId);
            if (groupId.equals("0")) {
                for (CustomerDetailsDO customerDetailsDO : list) {
                    String companyId = customerDetailsDO.getCompanyId();
                    HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO = getHrSummaryVoByCompany(
                            companyId,
                            companyIdNameMap.get(companyId),
                            hrMonthlySalaryQuery.getYearly(),
                            hrMonthlySalaryQuery.getMonthly(),
                            customerDetailsDO);
                    voList.add(hrMonthlySalarySummaryVO);
                }
            } else {
                List<HrMonthlySalarySummaryVO> companySummaryList = new ArrayList<>();
                for (CustomerDetailsDO customerDetailsDO : list) {
                    String companyId = customerDetailsDO.getCompanyId();
                    HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO = getHrSummaryVoByCompany(
                            companyId,
                            companyIdNameMap.get(companyId),
                            hrMonthlySalaryQuery.getYearly(),
                            hrMonthlySalaryQuery.getMonthly(),
                            customerDetailsDO);
                    companySummaryList.add(hrMonthlySalarySummaryVO);

                }

                HrMonthlySalarySummaryVO hrSummaryVoByGroup = getHrSummaryVoByGroup(
                        groupId,
                        groupIdNameMap.get(groupId),
                        hrMonthlySalaryQuery.getYearly(),
                        hrMonthlySalaryQuery.getMonthly(),
                        companySummaryList,
                        groupIdPidMap);

                voList.add(hrSummaryVoByGroup);
            }
        }

        //6、根据权限，生成客户明细表的结构
        List<ChildCompanyListVO> list = childCompanyService.select(new ChildCompanyQuery(), tokenUser);
        hrMonthlySalarySummaryVOList = makeTree(list);

        //7、把客户明细表加到对应的结构上
        hrMonthlySalarySummaryVOList = treeAddDate(hrMonthlySalarySummaryVOList, voList);


        //8、排除没有客户明细的分支
        hrMonthlySalarySummaryVOList = filterNullCompany(hrMonthlySalarySummaryVOList, companyIdCustomerDetailsMap, groupIds);
        hrMonthlySalarySummaryVOList = filterNullGroup(hrMonthlySalarySummaryVOList);

        //7、刷新父节点的几个客户明细表的聚合数据
        for (HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO : hrMonthlySalarySummaryVOList) {
            calEmpNum(hrMonthlySalarySummaryVO);
        }

        //把这个客户明细表树，转map,根据参数查询就行
//        Map<String, List<HrMonthlySalarySummaryVO>> customerDetailMap = hrMonthlySalarySummaryVOList.parallelStream()
//                .collect(Collectors.groupingBy(HrMonthlySalarySummaryVO::getSubjectId));
//
//        if (hrMonthlySalaryQuery.getType().getType().equals("site")) {
//            return hrMonthlySalarySummaryVOList.get(0).getHrMonthlySalarySummaryVOList();
//        } else {
//            return customerDetailMap.get(hrMonthlySalaryQuery.getType().getId());
//        }

        return hrMonthlySalarySummaryVOList.get(0).getHrMonthlySalarySummaryVOList();

    }


    /**
     * 排除没有生成客户明细表的用工单位结构
     *
     * @param hrMonthlySalarySummaryVOList
     * @return
     */
    private List<HrMonthlySalarySummaryVO> filterNullCompany(
            List<HrMonthlySalarySummaryVO> hrMonthlySalarySummaryVOList,
            Map<String, List<CustomerDetailsDO>> map,
            List<String> groupIds) {

        Iterator<HrMonthlySalarySummaryVO> it = hrMonthlySalarySummaryVOList.iterator();
        while (it.hasNext()) {
            HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO = it.next();

            List<HrMonthlySalarySummaryVO> childList = hrMonthlySalarySummaryVO.getHrMonthlySalarySummaryVOList();
            if (!CollectionUtils.isEmpty(childList)) {
                filterNullCompany(childList, map, groupIds);
            }

            String type = hrMonthlySalarySummaryVO.getType();
            String subjectId = hrMonthlySalarySummaryVO.getSubjectId();
            if ("company".equals(type) && map.get(subjectId) == null) {
                it.remove();
            }

//            if (type.equals("group") && groupIds !=null && !groupIds.contains(subjectId)) {
//                it.remove();
//            }
        }
        return hrMonthlySalarySummaryVOList;
    }


    private List<HrMonthlySalarySummaryVO> filterNullGroup(
            List<HrMonthlySalarySummaryVO> hrMonthlySalarySummaryVOList) {

        Iterator<HrMonthlySalarySummaryVO> it = hrMonthlySalarySummaryVOList.iterator();
        while (it.hasNext()) {
            HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO = it.next();

            List<HrMonthlySalarySummaryVO> childList = hrMonthlySalarySummaryVO.getHrMonthlySalarySummaryVOList();
            if (!CollectionUtils.isEmpty(childList)) {
                filterNullGroup(childList);
            }
            String type = hrMonthlySalarySummaryVO.getType();
            if (type.equals("group") && CollectionUtils.isEmpty(hrMonthlySalarySummaryVO.getHrMonthlySalarySummaryVOList())) {
                it.remove();
            }
        }
        return hrMonthlySalarySummaryVOList;
    }

    /**
     * 把客户明细表加到对应的结构上
     *
     * @param tree 客户明细表结构
     * @param data 客户明细表数据
     * @return
     */
    private List<HrMonthlySalarySummaryVO> treeAddDate(
            List<HrMonthlySalarySummaryVO> tree,
            List<HrMonthlySalarySummaryVO> data) {

        for (int i = 0; i < tree.size(); i++) {
            HrMonthlySalarySummaryVO treeVo = tree.get(i);
//                log.info("treeVo:" + treeVo.getName());
            List<HrMonthlySalarySummaryVO> childList = treeVo.getHrMonthlySalarySummaryVOList();
            if (!CollectionUtils.isEmpty(childList)) {
                treeAddDate(childList, data);
            }
            String treeSubjectId = treeVo.getSubjectId();

            for (HrMonthlySalarySummaryVO dataVo : data) {
//                    log.info("dataVo:" + dataVo.getName());
                String dataSubjectId = dataVo.getSubjectId();
                List<HrMonthlySalarySummaryVO> dataVoList = dataVo.getHrMonthlySalarySummaryVOList();
                if (dataSubjectId.equals(treeSubjectId)) {
                    //                    tree.set(i, dataVo);
                    //data的子集更新到tree的子集上，如果data的少，tree的多，就保留tree的
                    List<HrMonthlySalarySummaryVO> treeList = treeVo.getHrMonthlySalarySummaryVOList();
                    if (!CollectionUtils.isEmpty(treeList)) {
                        for (int j = 0; j < treeList.size(); j++) {
                            HrMonthlySalarySummaryVO treeChild = treeList.get(j);
                            for (int k = 0; k < dataVoList.size(); k++) {
                                HrMonthlySalarySummaryVO dataChild = dataVoList.get(k);
                                if (treeChild.getSubjectId().equals(dataChild.getSubjectId())) {
                                    //                                    treeChild = dataChild;
                                    BeanUtils.copyProperties(dataChild, treeChild);
                                    break;
                                }
                            }
                        }
                        dataVo.setHrMonthlySalarySummaryVOList(treeList);
                    }
                    //tree
                    BeanUtils.copyProperties(dataVo, treeVo);
                    break;
                }
            }
        }

        return tree;
    }

    private Map<String, String> searchParent(List<ChildCompanyListVO> list) {
        Map map = new HashMap();
        for (ChildCompanyListVO childCompanyListVO : list) {
            String id = childCompanyListVO.getId();
            String parentId = childCompanyListVO.getParentId();
            map.put(id, parentId);
            if (!CollectionUtils.isEmpty(childCompanyListVO.getCompanyList())) {
                map.putAll(searchParent(childCompanyListVO.getCompanyList()));
            }
        }
        return map;
    }


    /**
     * 客户明细表，向上查询,拼接出最上层
     *
     * @param list 有权限的分组
     * @return
     */
    private List<HrMonthlySalarySummaryVO> makeTree(
            List<ChildCompanyListVO> list) {
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        List<HrMonthlySalarySummaryVO> result = new ArrayList<>();
        for (ChildCompanyListVO childCompanyListVO : list) {
            HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO = new HrMonthlySalarySummaryVO();
            hrMonthlySalarySummaryVO.setName(childCompanyListVO.getName());
            hrMonthlySalarySummaryVO.setType(childCompanyListVO.getType());
            hrMonthlySalarySummaryVO.setSubjectId(childCompanyListVO.getId());
            hrMonthlySalarySummaryVO.setPSubjectId(childCompanyListVO.getParentId());
            hrMonthlySalarySummaryVO.setHrMonthlySalarySummaryVOList(makeTree(childCompanyListVO.getCompanyList()));
            result.add(hrMonthlySalarySummaryVO);
        }
        return result;
    }


    /**
     * 返回租户id集合、用工单位id集合
     *
     * @param type
     * @param userCompanyVO
     * @param siteId
     * @return
     */
    @Override
    public Map<String, List<String>> filterCustomerDetailCompanyIds(TypeAndId type,
                                                                    UserCompanyVO userCompanyVO,
                                                                    String siteId) {
        List<String> sourcepermissionGroupIds = userCompanyVO.getAllGroupIds();
        List<String> sourcepermissionCompanyIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(userCompanyVO.getCompanyIds())) {
            sourcepermissionCompanyIds.addAll(userCompanyVO.getCompanyIds());
        }

        List<String> permissionGroupIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(userCompanyVO.getAllGroupIds())) {
            permissionGroupIds.addAll(userCompanyVO.getAllGroupIds());
        }

        List<String> permissionCompanyIds = userCompanyVO.getCompanyIds();

        List<ChildCompanyDO> list = selectBySiteId(siteId);
        list = TreeKit.toTreeList(list);

        //根据用工单位，反查上级所有分组（一直向上找到根节点）
        List<GroupCompanyDO> pGroup = groupCompanyService.selectByCompanyIds(permissionCompanyIds, siteId);
        List<String> companyGroupId = pGroup.stream().map(GroupCompanyDO::getGroupId).collect(Collectors.toList());
        companyGroupId = findPIds(list, companyGroupId);
        if (!CollectionUtils.isEmpty(companyGroupId)) {
            permissionGroupIds.addAll(companyGroupId);
        }

        // 拿着用工单位，查询上级分组
        boolean isAllChildCompany = userCompanyVO.getIsAllChildCompany();

        Map<String, List<String>> map = new HashMap<>();
        List<String> groupList = new ArrayList<>(); //能看到的分组
        List<String> companyList = new ArrayList<>();//能看到的用工单位
        List<String> permissionGroupAndCompanyIds = new ArrayList<>();//有权限的用工单位，或者有权限的分组下的用工单位

        if (type != null && StringUtils.isNotBlank(type.getType()) && StringUtils.isNotBlank(type.getId())) {
            switch (type.getType()) {
                case "site":
                    //如果是租户id,查询租户所有的分组和没有分组的用工单位
                    List<ChildCompanyDO> siteChildTree = childCompanyDAO.findTreeByParentIdSiteId("0", siteId);
                    List<ChildCompanyDO> siteChildList = ListKit.treeToList(siteChildTree);
                    List<String> siteGroupTreeIds = siteChildList.stream().map(ChildCompanyDO::getId).collect(Collectors.toList());

                    for (String groupTreeId : siteGroupTreeIds) {
                        if (isAllChildCompany || permissionGroupIds.contains(groupTreeId)) {
                            groupList.add(groupTreeId);
                        }
                    }
                    map.put("group", groupList);

                    //直属租户的用工单位
                    List<CompanyVO> siteCompanyList = groupCompanyDAO.companyListBySiteId(siteId);

                    for (CompanyVO companyVO : siteCompanyList) {
                        if (isAllChildCompany || permissionCompanyIds.contains(companyVO.getId())) {
                            companyList.add(companyVO.getId());
                        }
                    }
                    map.put("company", companyList);

                    //查询groupList下面的用工单位集合
                    if (isAllChildCompany) {
                        List<String> companyIds = groupCompanyService.selectCompanyIdListByGroupIds(groupList, siteId);
                        if (!CollectionUtils.isEmpty(companyList)) {
                            companyIds.addAll(companyList);
                        }
                        map.put("permissionGroupAndCompanyIds", companyIds);
                    } else {
                        List<String> companyIds = groupCompanyService.selectCompanyIdListByGroupIds(sourcepermissionGroupIds, siteId);
                        if (!CollectionUtils.isEmpty(sourcepermissionCompanyIds)) {
                            companyIds.addAll(sourcepermissionCompanyIds);
                        }
                        map.put("permissionGroupAndCompanyIds", companyIds);
                    }

                    break;
                case "group":
                    //如果是分组id,查询分组树
                    List<String> groupIds = new ArrayList<>();
                    groupIds.add(type.getId());
                    List<ChildCompanyDO> childTree = childCompanyDAO.groupTreeIds(groupIds, siteId);
                    List<ChildCompanyDO> childList = ListKit.treeToList(childTree);
                    List<String> groupTreeIds = childList.stream().map(ChildCompanyDO::getId).collect(Collectors.toList());
                    for (String groupTreeId : groupTreeIds) {
                        if (isAllChildCompany || permissionGroupIds.contains(groupTreeId)) {
                            groupList.add(groupTreeId);
                        }
                    }
                    map.put("group", groupList);//能看到的分组

                    //有权限的用工单位
                    List<String> companyIds = groupCompanyService.selectCompanyIdListByGroupIds(sourcepermissionGroupIds, siteId);
                    if (!CollectionUtils.isEmpty(sourcepermissionCompanyIds)) {
                        companyIds.addAll(sourcepermissionCompanyIds);
                    }

                    //查询groupList下面的用工单位集合
                    List<String> group4CompanyIds = groupCompanyService.selectCompanyIdListByGroupIds(groupList, siteId);
                    if (isAllChildCompany) {
                        map.put("permissionGroupAndCompanyIds", group4CompanyIds);
                    } else {
                        for (Iterator<String> iterator = group4CompanyIds.iterator(); iterator.hasNext(); ) {
                            String companyId = iterator.next();
                            if (!companyIds.contains(companyId)) {
                                iterator.remove();
                            }
                        }
                        map.put("permissionGroupAndCompanyIds", group4CompanyIds);
                    }
                    break;
                case "company":
                    //如果是用工单位，就返回某个用工单位
                    companyList.add(type.getId());
                    map.put("company", companyList);
                    map.put("permissionGroupAndCompanyIds", companyList);
                    break;
                default:
            }
        }
        return map;
    }

    /**
     * 客户明细表，树转平铺
     *
     * @param hrMonthlySalarySummaryVOList
     * @return
     */
    private List<HrMonthlySalarySummaryVO> salaryTreeToList(List<HrMonthlySalarySummaryVO> hrMonthlySalarySummaryVOList) {
        if (CollectionUtils.isEmpty(hrMonthlySalarySummaryVOList)) {
            return hrMonthlySalarySummaryVOList;
        }
        List<HrMonthlySalarySummaryVO> result = new ArrayList<>();
        result.addAll(hrMonthlySalarySummaryVOList);
        for (HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO : hrMonthlySalarySummaryVOList) {
            if (!CollectionUtils.isEmpty(hrMonthlySalarySummaryVO.getHrMonthlySalarySummaryVOList())) {
                List<HrMonthlySalarySummaryVO> child = salaryTreeToList(hrMonthlySalarySummaryVO.getHrMonthlySalarySummaryVOList());
                if (!CollectionUtils.isEmpty(child)) {
                    result.addAll(child);
                }
            }
        }
        return result;
    }

    /**
     * @param current 当前客户明细表
     * @return
     */
    private void calEmpNum(HrMonthlySalarySummaryVO current) {
        List<HrMonthlySalarySummaryVO> child = current.getHrMonthlySalarySummaryVOList();
        if (!CollectionUtils.isEmpty(child)) {
            //计薪人数
            int empNum = 0;
            //应发
            BigDecimal shouldWages = new BigDecimal(0);
            //实发
            BigDecimal paidWages = new BigDecimal(0);
            //个税
            BigDecimal tax = new BigDecimal(0);
            //企业成本
            BigDecimal businessCost = new BigDecimal(0);
            //服务费
            BigDecimal serviceCharge = new BigDecimal(0);
            // 公司社保
            BigDecimal enterpriseSocialSecurity = new BigDecimal(0);
            // 企业公积金
            BigDecimal enterpriseProvidentFund = new BigDecimal(0);
            // 客户费用
            BigDecimal customerFees = new BigDecimal(0);
            //滞纳金
            BigDecimal fine = new BigDecimal(0);
            // 人力成本
            BigDecimal laborCost = new BigDecimal(0);

            List<String> companyIds = current.getCompanyIds();
            List<Long> customerDetailsIds = current.getCustomerDetailsIds();

            String personalPeriod = "";

            for (HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO : child) {
                calEmpNum(hrMonthlySalarySummaryVO);

                empNum += hrMonthlySalarySummaryVO.getEmpNumber() != null ? hrMonthlySalarySummaryVO.getEmpNumber() : 0;
                shouldWages = shouldWages.add(hrMonthlySalarySummaryVO.getShouldWages() != null ? hrMonthlySalarySummaryVO.getShouldWages() : new BigDecimal(0));
                paidWages = paidWages.add(hrMonthlySalarySummaryVO.getPaidWages() != null ? hrMonthlySalarySummaryVO.getPaidWages() : new BigDecimal(0));
                tax = tax.add(hrMonthlySalarySummaryVO.getTax() != null ? hrMonthlySalarySummaryVO.getTax() : new BigDecimal(0));

                businessCost = businessCost.add(hrMonthlySalarySummaryVO.getBusinessCost() != null ? hrMonthlySalarySummaryVO.getBusinessCost() : new BigDecimal(0));
                serviceCharge = serviceCharge.add(hrMonthlySalarySummaryVO.getServiceCharge() != null ? hrMonthlySalarySummaryVO.getServiceCharge() : new BigDecimal(0));
                enterpriseSocialSecurity = enterpriseSocialSecurity.add(hrMonthlySalarySummaryVO.getEnterpriseSocialSecurity() != null ? hrMonthlySalarySummaryVO.getEnterpriseSocialSecurity() : new BigDecimal(0));
                enterpriseProvidentFund = enterpriseProvidentFund.add(hrMonthlySalarySummaryVO.getEnterpriseProvidentFund() != null ? hrMonthlySalarySummaryVO.getEnterpriseProvidentFund() : new BigDecimal(0));

                customerFees = customerFees.add(hrMonthlySalarySummaryVO.getCustomerFees() != null ? hrMonthlySalarySummaryVO.getCustomerFees() : new BigDecimal(0));
                fine = fine.add(hrMonthlySalarySummaryVO.getFine() != null ? hrMonthlySalarySummaryVO.getFine() : new BigDecimal(0));
                laborCost = laborCost.add(hrMonthlySalarySummaryVO.getLaborCost() != null ? hrMonthlySalarySummaryVO.getLaborCost() : new BigDecimal(0));

                if (hrMonthlySalarySummaryVO.getType().equals("group")) {
                    if (companyIds == null) {
                        companyIds = new ArrayList<>();
                    }
                    companyIds.addAll(hrMonthlySalarySummaryVO.getCompanyIds() != null ? hrMonthlySalarySummaryVO.getCompanyIds() : new ArrayList<>());

                    if (customerDetailsIds == null) {
                        customerDetailsIds = new ArrayList<>();
                    }
                    customerDetailsIds.addAll(hrMonthlySalarySummaryVO.getCustomerDetailsIds() != null ? hrMonthlySalarySummaryVO.getCustomerDetailsIds() : new ArrayList<>());
                }
                personalPeriod = hrMonthlySalarySummaryVO.getPersonalPeriod();
            }
            current.setEmpNumber(empNum);
            current.setShouldWages(shouldWages);
            current.setPaidWages(paidWages);
            current.setTax(tax);

            current.setBusinessCost(businessCost);
            current.setServiceCharge(serviceCharge);
            current.setEnterpriseSocialSecurity(enterpriseSocialSecurity);
            current.setEnterpriseProvidentFund(enterpriseProvidentFund);

            current.setCustomerFees(customerFees);
            current.setFine(fine);
            current.setLaborCost(laborCost);

            current.setCompanyIds(companyIds);
            current.setCustomerDetailsIds(customerDetailsIds);

            current.setPersonalPeriod(personalPeriod);
        }
    }

    /**
     * 根据跟节点，查询对应的分组集合、用工单位集合
     *
     * @param type
     * @return
     */
    private List<TypeAndId> calcTypeAndIdList(TypeAndId type,
                                              UserCompanyVO userCompanyVO,
                                              String siteId) {
        List<String> permissionGroupIds = userCompanyVO.getAllGroupIds();
        List<String> permissionCompanyIds = userCompanyVO.getCompanyIds();
        boolean isAllChildCompany = userCompanyVO.getIsAllChildCompany();

        List<TypeAndId> list = new ArrayList<>();
        if (type != null && StringUtils.isNotBlank(type.getType()) && StringUtils.isNotBlank(type.getId())) {
            switch (type.getType()) {
                case "site":
                    //如果是租户id,查询租户所有的分组和没有分组的用工单位
                    List<ChildCompanyDO> siteChildTree = childCompanyDAO.findTreeByParentIdSiteId("0", siteId);
                    List<ChildCompanyDO> siteChildList = ListKit.treeToList(siteChildTree);
                    List<String> siteGroupTreeIds = siteChildList.stream().map(ChildCompanyDO::getId).collect(Collectors.toList());
                    for (String groupTreeId : siteGroupTreeIds) {
                        if (isAllChildCompany || permissionGroupIds.contains(groupTreeId)) {
                            TypeAndId param = new TypeAndId();
                            param.setId(groupTreeId);
                            param.setType("group");
                            list.add(param);
                        }
                    }

                    List<CompanyVO> companyList = groupCompanyDAO.companyListBySiteId(siteId);
                    for (CompanyVO companyVO : companyList) {
                        if (isAllChildCompany || permissionCompanyIds.contains(companyVO.getId())) {
                            TypeAndId param = new TypeAndId();
                            param.setId(companyVO.getId());
                            param.setType("company");
                            list.add(param);
                        }
                    }
                    break;
                case "group":
                    //如果是分组id,查询分组树
                    List<String> groupIds = new ArrayList<>();
                    groupIds.add(type.getId());
                    List<ChildCompanyDO> childTree = childCompanyDAO.groupTreeIds(groupIds, siteId);
                    List<ChildCompanyDO> childList = ListKit.treeToList(childTree);
                    List<String> groupTreeIds = childList.stream().map(ChildCompanyDO::getId).collect(Collectors.toList());
                    for (String groupTreeId : groupTreeIds) {
                        if (isAllChildCompany || permissionGroupIds.contains(groupTreeId)) {
                            TypeAndId param = new TypeAndId();
                            param.setId(groupTreeId);
                            param.setType(type.getType());
                            list.add(param);
                        }
                    }
                    break;
                case "company":
                    //如果是用工单位，就返回某个用工单位
                    TypeAndId typeAndId = new TypeAndId();
                    typeAndId.setType(type.getType());
                    typeAndId.setId(type.getId());
                    list.add(typeAndId);
                    break;
                default:
            }
        }
        return list;
    }

    /**
     * 计算分组的合计值
     *
     * @param list 平铺的分组集合
     * @param map  按照组id分组的值
     * @return
     */
    private List<HrMonthlySalarySummaryVO> updateGroupNumber(List<HrMonthlySalarySummaryVO> list,
                                                             Map<String, List<HrMonthlySalarySummaryVO>> map) {
        for (HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO : list) {
            String subjectId = hrMonthlySalarySummaryVO.getSubjectId();

            Set keySet = map.keySet();
            Iterator it = keySet.iterator();
            while (it.hasNext()) {
                String k = (String) it.next();
                List<HrMonthlySalarySummaryVO> child = map.get(k);
                HrMonthlySalarySummaryVO result = hrMonthlySalarySummaryVO;
                result = getChildrenNumber(child, map, result);
                if (subjectId.equals(k)) {
                    hrMonthlySalarySummaryVO.setEmpNumber(result.getEmpNumber());
                }
            }
        }
        return list;
    }

    /**
     * 递归查询每个分组的合计
     *
     * @param child
     * @param map
     * @param result
     * @return
     */
    private HrMonthlySalarySummaryVO getChildrenNumber(List<HrMonthlySalarySummaryVO> child,
                                                       Map<String, List<HrMonthlySalarySummaryVO>> map,
                                                       HrMonthlySalarySummaryVO result) {
        for (HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO : child) {
            String subjectId = hrMonthlySalarySummaryVO.getSubjectId();
            List<HrMonthlySalarySummaryVO> childrenList = map.get(subjectId);
            if (childrenList != null && childrenList.size() != 0) {
                // 递归调用
                result = getChildrenNumber(childrenList, map, result);
            }
            int empNumber = 0;
            if (result.getEmpNumber() != null) {
                empNumber = result.getEmpNumber();
            }
            result.setEmpNumber(hrMonthlySalarySummaryVO.getEmpNumber() + empNumber);
        }
        return result;
    }

    private List<HrMonthlySalarySummaryVO> monthlySalarySummaryToTree(
            List<HrMonthlySalarySummaryVO> hrMonthlySalarySummaryVOList,
            List<ChildCompanyListVO> groupTree) {

        if (CollectionUtils.isEmpty(groupTree)) {
            return new ArrayList<>();
        }
        List<HrMonthlySalarySummaryVO> result = new ArrayList<>();
        for (ChildCompanyListVO childCompanyListVO : groupTree) {
            HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO = null;

            //权限树 跟 客户明细表 匹配，能匹配上就直接赋值
            for (HrMonthlySalarySummaryVO hrMonthlyVO : hrMonthlySalarySummaryVOList) {
                if (hrMonthlyVO.getSubjectId().equals(childCompanyListVO.getId())) {
                    hrMonthlySalarySummaryVO = hrMonthlyVO;
                    break;
                }
            }

            //匹配不上，就手动创建一个
            if (hrMonthlySalarySummaryVO == null) {
                hrMonthlySalarySummaryVO = new HrMonthlySalarySummaryVO();
                hrMonthlySalarySummaryVO.setName(childCompanyListVO.getName());
                hrMonthlySalarySummaryVO.setSubjectId(childCompanyListVO.getId());
                hrMonthlySalarySummaryVO.setPSubjectId(childCompanyListVO.getParentId());
                hrMonthlySalarySummaryVO.setCustomerDetailsIds(new ArrayList<>());
                hrMonthlySalarySummaryVO.setCompanyIds(new ArrayList<>());
                hrMonthlySalarySummaryVO.setType("group");
            }

            if (!CollectionUtils.isEmpty(childCompanyListVO.getCompanyList())) {
                hrMonthlySalarySummaryVO.setHrMonthlySalarySummaryVOList(
                        monthlySalarySummaryToTree(hrMonthlySalarySummaryVOList, childCompanyListVO.getCompanyList()));
            }

            result.add(hrMonthlySalarySummaryVO);
        }

        return result;
    }


//    private List<HrMonthlySalarySummaryVO> monthlySalarySummaryToTree(
//            List<HrMonthlySalarySummaryVO> hrMonthlySalarySummaryVOList) {
//        List<HrMonthlySalarySummaryVO> currList = new ArrayList(hrMonthlySalarySummaryVOList);
//        List<HrMonthlySalarySummaryVO> rootList = getRootList(currList);
//        if (CollectionUtils.isEmpty(rootList)) {
//            return currList;
//        } else {
//            currList.removeAll(rootList);
//            rootList.forEach((t) -> {
//                setChildren(currList, t);
//            });
//            return rootList;
//        }
//    }

    private static List<HrMonthlySalarySummaryVO> getRootList(List<HrMonthlySalarySummaryVO> sourceList) {
        return CollectionUtils.isEmpty(sourceList) ? sourceList : (List) sourceList.stream().filter((source) -> {
            return isRoot(source.getPSubjectId());
        }).collect(Collectors.toList());
    }

    private static void setChildren(List<HrMonthlySalarySummaryVO> sourceList,
                                    HrMonthlySalarySummaryVO parent) {
        List<HrMonthlySalarySummaryVO> childrenList = parent.getHrMonthlySalarySummaryVOList();
        if (childrenList == null) {
            childrenList = new ArrayList();
        }

        Iterator var3 = sourceList.iterator();

        HrMonthlySalarySummaryVO child;
        while (var3.hasNext()) {
            child = (HrMonthlySalarySummaryVO) var3.next();
            if (parent.getSubjectId().equals(child.getPSubjectId())) {
                ((List) childrenList).add(child);
            }
        }

        parent.setHrMonthlySalarySummaryVOList((List) childrenList);
        if (((List) childrenList).size() > 0) {
            sourceList.removeAll((Collection) childrenList);
            if (!CollectionUtils.isEmpty(sourceList)) {
                var3 = ((List) childrenList).iterator();

                while (var3.hasNext()) {
                    child = (HrMonthlySalarySummaryVO) var3.next();
                    setChildren(sourceList, child);
                }
            }
        }

    }

    private static boolean isRoot(Object parentId) {
        if (parentId == null) {
            return false;
        } else if (parentId instanceof String) {
            return "0".equals(parentId);
        } else if (parentId instanceof Long) {
            return (Long) parentId == 0L;
        } else if (parentId instanceof Integer) {
            return (Integer) parentId == 0;
        } else {
            return false;
        }
    }

    @Override
    public List<SalaryTemplateItemVO> selectUsedTemplateByCompanyList(Integer yearly, Integer monthly
            , String type, String id, TokenUser tokenUser) {
        List<String> companyIds = new ArrayList<>();
        if ("group".equals(type)) {
            companyIds = groupCompanyService.selectCompanyIdListByGroupId(id, tokenUser.getSiteId());
        } else if ("company".equals(type)) {
            companyIds.add(id);
        } else {
            throw new ParamException("查询类型有误，类型：" + type);
        }
        List<SalaryTemplateSalaryDO> salaryTemplateSalaryDOList = salaryProviderService
                .selectTemplateByCompanyIds(yearly, monthly, companyIds, tokenUser);
        if (CollectionUtils.isEmpty(salaryTemplateSalaryDOList)) {
            return new ArrayList<>();
        }
        return salaryProviderService.selectAllUsedVoBySalaryTemplateSalaryIds(salaryTemplateSalaryDOList
                .parallelStream().map(BaseDO::getId).collect(Collectors.toList()), tokenUser);
    }

    @Override
    public HeaderFieldsVO selectHeaderDetail(String subjectType, String subjectId, List<Long> customerDetailsIds
            , Integer yearly, Integer monthly, TokenUser tokenUser) {
        ParamException.notEmpty(customerDetailsIds, "客户信息信息有误，请联系管理员");
        HeaderFieldsVO headerFieldsVO = new HeaderFieldsVO();
        List<HeaderFieldsListVO> headerFieldsListVOList;
        String sourceId;
        if ("group".equals(subjectType)) {
            sourceId = "" + yearly + monthly;
            headerFieldsListVOList = selectAllCustomerHeaderDetail(subjectType, subjectId, sourceId, customerDetailsIds, tokenUser);
        } else if ("company".equals(subjectType)) {
            // 类型为用工单位
            Long customerDetailsId = customerDetailsIds.get(0);
            sourceId = customerDetailsId + "";
            // 自定表头
            List<HeaderFieldsDO> headerFieldsDOList = adminProviderService
                    .selectMyselfHeaderFieldsBySourceId(subjectType, subjectId, CUSTOMER.getValue(), sourceId, tokenUser);
            if (CollectionUtils.isEmpty(headerFieldsDOList)) {
                // 没创建自定义表头 取客户明细表表头
                headerFieldsListVOList = selectAllCustomerHeaderDetail(subjectType, subjectId, customerDetailsId, tokenUser);
            } else {
                // 已创建自定义表头
                headerFieldsListVOList = headerFieldsDOList.parallelStream().map(headerFieldsDO
                                -> headerFieldsDO.to(HeaderFieldsListVO.class))
                        .sorted(Comparator.comparing(HeaderFieldsListVO::getSort)).collect(Collectors.toList());
            }
        } else {
            throw new ParamException("查询类型有误，类型：" + subjectType);
        }
        // 可见表头字段
        List<HeaderFieldsListVO> canSee = new ArrayList<>();
        // 不可见表头字段
        List<HeaderFieldsListVO> ignore = new ArrayList<>();
        for (HeaderFieldsListVO headerFieldsListVO : headerFieldsListVOList) {
            if (headerFieldsListVO.getIsOpen()) {
                canSee.add(headerFieldsListVO);
            } else {
                ignore.add(headerFieldsListVO);
            }
        }
        headerFieldsVO.setId("all");
        headerFieldsVO.setSubjectType(subjectType);
        headerFieldsVO.setSubjectId(subjectId);
        headerFieldsVO.setModuleCode(CUSTOMER.getValue());
        headerFieldsVO.setSourceId(sourceId);
        headerFieldsVO.setCanSee(canSee);
        headerFieldsVO.setIgnore(ignore);
        return headerFieldsVO;
    }

    @Override
    public List<ChildCompanyVO> tree(ChildCompanyQuery childCompanyQuery, TokenUser tokenUser) {

        Example example = new Example(ChildCompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId());
        // 站点下所有分组信息
        List<ChildCompanyDO> childCompanyDOList = childCompanyDAO.selectByExample(example);

        //过滤当前登录人，有权限的用工单位分组和用工单位
        UserCompanyVO userCompanyVO = selectByUserId(tokenUser.getUserId(), tokenUser.getSiteId());
        if (userCompanyVO.getIsAllChildCompany()) {
            // 拥有全部用工单位权限 所有分组都需要给予修改权限
            childCompanyDOList.parallelStream().forEach(childCompanyDO -> childCompanyDO.setHasPermission(Boolean.TRUE));
        } else {
            // 有权限的分组 给与修改权限
            List<String> allGroupIds = userCompanyVO.getAllGroupIds();
            childCompanyDOList.parallelStream().forEach(childCompanyDO
                    -> childCompanyDO.setHasPermission(allGroupIds.contains(childCompanyDO.getId())));
        }

        // 平铺的List 转成树形List
        childCompanyDOList = TreeKit.toTreeList(childCompanyDOList);
        List<ChildCompanyVO> childCompanyResult = childCompanyDOList.stream().map(childCompanyDO
                -> childCompanyDO.to(ChildCompanyVO.class)).collect(Collectors.toList());
        //顶层加上租户信息
        ChildCompanyVO siteVo = new ChildCompanyVO();
        SiteVO siteVO = siteProviderService.selectById(tokenUser.getSiteId(), null);
        siteVo.setName(siteVO.getName());
        siteVo.setId("0");
        siteVo.setLevel(1);
        siteVo.setEdit(false);
        siteVo.setChildList(childCompanyResult);
        siteVo.setHasPermission(Boolean.FALSE);
        List<ChildCompanyVO> result = new ArrayList<>();
        result.add(siteVo);
        return result;

    }

    private List<ChildCompanyVO> filterPermissionByTree(List<ChildCompanyVO> childCompanyResult,
                                                        UserCompanyVO userCompanyVO,
                                                        String siteId) {
        if (userCompanyVO.getIsAllChildCompany()) {
            //如果全部，直接返回不用过滤
            return childCompanyResult;
        } else {
            //有权限的分组集合
            List<String> groupIds = userCompanyVO.getGroupIds();

            List<ChildCompanyDO> list = selectBySiteId(siteId);
            list = TreeKit.toTreeList(list);

            //根据父分组查询子分组集合
            if (!CollectionUtils.isEmpty(groupIds)) {
                List<ChildCompanyDO> childCompanyTreee = childCompanyDAO.groupTreeIds(groupIds, siteId);
                childCompanyTreee = ListKit.treeToList(childCompanyTreee);
                groupIds = childCompanyTreee.stream().map(ChildCompanyDO::getId).collect(Collectors.toList());//分组的所有下级分组

            }

            //查询分组的所有上级分组
            List<String> groupPIds = findPIds(list, groupIds);//分组的上级分组

            groupIds.addAll(groupPIds);//分组的所有上级分组

            //更新分组树，哪个分支有权限
            setPermissionByTree(childCompanyResult, groupIds);

            //过滤分组树，排除没有权限的分支
            filterByPermissionByTree(childCompanyResult);

            return childCompanyResult;
        }
    }


    private void setPermissionByTree(List<ChildCompanyVO> childCompanyResult, List<String> groupIds) {
        //更新分组树，哪个分支有权限
        for (ChildCompanyVO childCompanyVO : childCompanyResult) {
            String id = childCompanyVO.getId();
            if (groupIds.contains(id)) {
                childCompanyVO.setHasPermission(true);
            }
            if (!CollectionUtils.isEmpty(childCompanyVO.getChildList())) {
                setPermissionByTree((List<ChildCompanyVO>) childCompanyVO.getChildList(), groupIds);
            }
        }
    }

    private void filterByPermissionByTree(List<ChildCompanyVO> childCompanyResult) {
        Iterator<ChildCompanyVO> itr = childCompanyResult.iterator();
        while (itr.hasNext()) {
            ChildCompanyVO childCompanyVO = itr.next();
            if (childCompanyVO.getHasPermission() == null || !childCompanyVO.getHasPermission()) {
                itr.remove();
            } else {
                if (!CollectionUtils.isEmpty(childCompanyVO.getChildList())) {
                    filterByPermission((List<ChildCompanyListVO>) childCompanyVO.getChildList());
                }
            }
        }
    }


    @Override
    public List<ChildCompanyDO> groupTree(List<String> groupIds, String siteId) {
        return childCompanyDAO.groupTreeIds(groupIds, siteId);
    }

    @Override
    public List<String> groupTreeIds(List<String> groupIds, String siteId) {
        List<ChildCompanyDO> list = childCompanyDAO.groupTreeIds(groupIds, siteId);
        list = ListKit.treeToList(list);
        return list.stream().map(ChildCompanyDO::getId).collect(Collectors.toList());
    }

    @Override
    public ChildCompanyDO selectByName(String s, TokenUser tokenUser) {
        Example example = new Example(ChildCompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId())
                .andEqualTo("name", s);
        List<ChildCompanyDO> list = childCompanyDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }


    /**
     * 获取用工单位分组级客户明细表表头
     *
     * @param subjectType        业务类型
     * @param subjectId          业务Id
     * @param sourceId           来源Id(年 + 月)
     * @param customerDetailsIds 客户明细Ids
     * @param tokenUser          当前用户
     * @return 用工单位分组级客户明细表表头
     */
    private List<HeaderFieldsListVO> selectAllCustomerHeaderDetail(String subjectType, String subjectId
            , String sourceId, List<Long> customerDetailsIds, TokenUser tokenUser) {
        List<HeaderFieldsListVO> headerFieldsListVOList = new ArrayList<>();
        // 自定义表头
        List<HeaderFieldsDO> headerFieldsDOList = adminProviderService
                .selectMyselfHeaderFieldsBySourceId(subjectType, subjectId, CUSTOMER.getValue(), sourceId, tokenUser);
        // 客户明细表表头
        List<CustomerDetailsDO> customerDetailsDOList = salaryProviderService.selectCustomerDetailsByIds(customerDetailsIds, tokenUser);
        String headerString = customerDetailsDOList.parallelStream().map(CustomerDetailsDO::getHeader)
                .filter(StringUtils::isNotBlank).collect(Collectors.joining(","));
        List<String> headerList = Arrays.stream(headerString.split(",")).distinct().collect(Collectors.toList());
        boolean hadEmpName = headerList.remove("姓名");
        boolean hadIdCard = headerList.remove("身份证号");
        boolean hadShouldWages = headerList.remove("应发工资");
        boolean hadSocCity = headerList.remove("参保城市");
        boolean hadEmpSocialSecurity = headerList.remove("个人社保");
        boolean hadEnterpriseSocialSecurity = headerList.remove("企业社保");
        boolean hadEmpProvidentFund = headerList.remove("个人公积金");
        boolean hadEnterpriseProvidentFund = headerList.remove("企业公积金");
        boolean hadTax = headerList.remove("个人所得税");
        boolean hadPaidWages = headerList.remove("实发工资");
        boolean hadServiceCharge = headerList.remove("服务费");
        boolean hadFine = headerList.remove("滞纳金");
        // 构建表头数据
        HeaderFieldsListVO headerFieldsListVO = new HeaderFieldsListVO();
        headerFieldsListVO.setSubjectType(subjectType);
        headerFieldsListVO.setSubjectId(subjectId);
        headerFieldsListVO.setSourceId(sourceId);
        headerFieldsListVO.setModuleCode(CUSTOMER.getValue());
        headerFieldsListVO.setIsEdit(true);
        headerFieldsListVO.setModuleType("客户明细");
        // 未创建自定义
        if (hadEmpName) {
            headerList.add(0, "姓名");
        }
        if (hadIdCard) {
            headerList.add(1, "身份证号");
        }
        if (hadSocCity) {
            headerList.add(2, "参保城市");
        }
        if (hadShouldWages) {
            headerList.add("应发工资");
        }
        if (hadEmpSocialSecurity) {
            headerList.add("个人社保");
        }
        if (hadEmpProvidentFund) {
            headerList.add("个人公积金");
        }
        if (hadTax) {
            headerList.add("个人所得税");
        }
        if (hadPaidWages) {
            headerList.add("实发工资");
        }
        if (hadEnterpriseSocialSecurity) {
            headerList.add("企业社保");
        }
        if (hadEnterpriseProvidentFund) {
            headerList.add("企业公积金");
        }
        if (hadServiceCharge) {
            headerList.add("服务费");
        }
        if (hadFine) {
            headerList.add("滞纳金");
        }
        Map<String, Boolean> fieldNameIsOpenMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(headerFieldsDOList)) {
            // 已创建自定义
            fieldNameIsOpenMap = headerFieldsDOList.parallelStream().collect(Collectors
                    .toMap(HeaderFieldsDO::getFieldName, HeaderFieldsDO::getIsOpen));
        }
        for (int i = 0; i < headerList.size(); i++) {
            String header = headerList.get(i);
            HeaderFieldsListVO empName = headerFieldsListVO.to(HeaderFieldsListVO.class);
            empName.setFieldName(header);
            empName.setFieldEnName(SalaryConstants.CUSTOMER_DETAILS_MAP.get(header));
            empName.setSort(i);
            if (fieldNameIsOpenMap.get(header) == null) {
                empName.setIsOpen(true);
            } else {
                empName.setIsOpen(fieldNameIsOpenMap.get(header));
            }
            headerFieldsListVOList.add(empName);
        }
        return headerFieldsListVOList;
    }


    /**
     * 获取用工单位级客户明细表表头
     *
     * @param subjectType       业务类型
     * @param subjectId         业务Id
     * @param customerDetailsId 客户明细Id
     * @param tokenUser         当前用户
     * @return 用工单位级客户明细表表头
     */
    private List<HeaderFieldsListVO> selectAllCustomerHeaderDetail(String subjectType, String subjectId
            , Long customerDetailsId, TokenUser tokenUser) {
        List<HeaderFieldsListVO> headerFieldsListVOList = new ArrayList<>();
        CustomerDetailsDO customerDetailsDO = salaryProviderService.selectCustomerDetailsById(customerDetailsId, tokenUser);
        ParamException.notNull(customerDetailsDO, "该客户明细已不存在，请刷新后重试");
        List<String> headerList = new ArrayList<>(Arrays.asList(customerDetailsDO.getHeader().split(",")));
        HeaderFieldsListVO headerFieldsListVO = new HeaderFieldsListVO();
        headerFieldsListVO.setSubjectType(subjectType);
        headerFieldsListVO.setSubjectId(subjectId);
        headerFieldsListVO.setSourceId(customerDetailsId + "");
        headerFieldsListVO.setModuleCode(CUSTOMER.getValue());
        headerFieldsListVO.setIsOpen(true);
        headerFieldsListVO.setIsEdit(true);
        headerFieldsListVO.setModuleType("客户明细");
        for (int i = 0; i < headerList.size(); i++) {
            String header = headerList.get(i);
            HeaderFieldsListVO empName = headerFieldsListVO.to(HeaderFieldsListVO.class);
            empName.setFieldName(header);
            empName.setFieldEnName(SalaryConstants.CUSTOMER_DETAILS_MAP.get(header));
            empName.setSort(i);
            headerFieldsListVOList.add(empName);
        }
        return headerFieldsListVOList;
    }


    @Override
    public Page<EmployeeDetailsVO> selectEmployeeSalaryPageByCompanyIds(HrEmployeeSalaryQuery hrEmployeeSalaryQuery
            , TokenUser tokenUser) {
        List<EmployeeDetailsVO> employeeSalaryVOList = selectEmployeeSalaryByCompanyIds(hrEmployeeSalaryQuery, tokenUser);
        if (CollectionUtils.isEmpty(employeeSalaryVOList)) {
            return new Page<>(hrEmployeeSalaryQuery.getPageSize(), hrEmployeeSalaryQuery.getPageNo());
        }
        return PageKit.startPage(employeeSalaryVOList, hrEmployeeSalaryQuery.getPageNo(), hrEmployeeSalaryQuery.getPageSize());
    }


    private List<EmployeeDetailsVO> selectEmployeeSalaryByCompanyIds(HrEmployeeSalaryQuery hrEmployeeSalaryQuery
            , TokenUser tokenUser) {
        List<Long> customerDetailsIdList = hrEmployeeSalaryQuery.getCustomerDetailsIdList();
        if (CollectionUtils.isEmpty(customerDetailsIdList)) {
            return new ArrayList<>();
        }
        List<EmployeeDetailsDO> employeeDetailsDOList = salaryProviderService
                .selectEmployeeDetailsByCustomerDetailsIdList(customerDetailsIdList, tokenUser);
        if (CollectionUtils.isEmpty(employeeDetailsDOList)) {
            return new ArrayList<>();
        }
        // 员工Id
        List<String> empIds = employeeDetailsDOList.parallelStream().map(EmployeeDetailsDO::getEmpId).distinct().collect(Collectors.toList());
        // 员工信息
        List<EmpInfoDO> empInfoDOList = empInfoService.selectDoByIdsIgnoreValid(empIds);
        Map<String, EmpInfoDO> empInfoDOMap = empInfoDOList.parallelStream().collect(Collectors.toMap(BaseDO::getId, v -> v));
        return employeeDetailsDOList.parallelStream().map(employeeDetailsDO -> {
            EmployeeDetailsVO employeeDetailsVO = employeeDetailsDO.to(EmployeeDetailsVO.class);
            // 放入员工信息
            EmpInfoDO empInfoDO = empInfoDOMap.get(employeeDetailsDO.getEmpId());
            if (empInfoDO != null) {
                employeeDetailsVO.setIdCard(empInfoDO.getIdCard());
                employeeDetailsVO.setPhone(empInfoDO.getPhone());
                employeeDetailsVO.setEmpStatus(empInfoDO.getStatus());
            } else {
                employeeDetailsVO.setIdCard("");
                employeeDetailsVO.setPhone("");
                employeeDetailsVO.setEmpStatus(0);
            }
            // 姓名、手机号、身份证号
            if (StringUtils.isNotBlank(hrEmployeeSalaryQuery.getNameOrPhoneOrIdCard())) {
                if (!employeeDetailsVO.getEmpName().contains(hrEmployeeSalaryQuery.getNameOrPhoneOrIdCard())
                        && !employeeDetailsVO.getIdCard().contains(hrEmployeeSalaryQuery.getNameOrPhoneOrIdCard())
                        && !employeeDetailsVO.getPhone().contains(hrEmployeeSalaryQuery.getNameOrPhoneOrIdCard())) {
                    return null;
                }
            }
            // 员工状态筛选
            if (hrEmployeeSalaryQuery.getEmpStatus() != null
                    && !hrEmployeeSalaryQuery.getEmpStatus().equals(employeeDetailsVO.getEmpStatus())) {
                return null;
            }
            return employeeDetailsVO;
        }).filter(Objects::nonNull).parallel().collect(Collectors.toList());
    }

//    @Override
//    public List<EmployeeSalaryVO> selectEmployeeSalaryListByTypeAndId(HrEmployeeSalaryQuery hrEmployeeSalaryQuery, TokenUser tokenUser) {
//        List<String> companyIds;
//        if ("group".equals(hrEmployeeSalaryQuery.getType())) {
//            companyIds = groupCompanyService.selectCompanyIdListByGroupId(hrEmployeeSalaryQuery.getId(), tokenUser.getSiteId());
//            // 分组下公司为空
//            if (CollectionUtils.isEmpty(companyIds)) {
//                return new ArrayList<>();
//            }
//        } else if ("company".equals(hrEmployeeSalaryQuery.getType())) {
//            companyIds = Collections.singletonList(hrEmployeeSalaryQuery.getId());
//        } else {
//            throw new ParamException("传入类型有误");
//        }
//        return selectEmployeeSalaryListByCompanyIds(hrEmployeeSalaryQuery.getYearly(), hrEmployeeSalaryQuery.getMonthly()
//                , hrEmployeeSalaryQuery.getNameOrPhoneOrIdCard(), hrEmployeeSalaryQuery.getEmpStatus(), companyIds, tokenUser);
//    }


//    @Override
//    public List<EmployeeSalaryVO> selectEmployeeSalaryListByCompanyIds(Integer yearly, Integer monthly
//            , String nameOrPhoneOrIdCard, Integer empStatus, List<String> companyIds, TokenUser tokenUser) {
//
//        // 已创建的员工月工资
//        List<EmployeeSalaryDO> employeeSalaryDOList = salaryProviderService.selectByCompanyIdsAndMonthly(companyIds
//                , yearly, monthly, tokenUser);
//        // 创建月工资的员工
//        List<String> empIds = employeeSalaryDOList.parallelStream()
//                .map(EmployeeSalaryDO::getEmpId).distinct().collect(Collectors.toList());
//        List<EmpInfoDO> empInfoDOList = empInfoService.selectDoByIds(empIds);
//        // 员工Id-DO
//        Map<String, EmpInfoDO> empIdDoMap = empInfoDOList.parallelStream()
//                .collect(Collectors.toMap(BaseDO::getId, v -> v));
//        // 社保信息
//        List<EmpSocInfoVO> empSocInfoVOList = empSocInfoService
//                .selectEmpSocInfoWithCustomerDetails(yearly, monthly, companyIds, tokenUser);
//        Map<String, EmpSocInfoVO> empIdEmpSocInfoVoMap = empSocInfoVOList.parallelStream()
//                .collect(Collectors.toMap(EmpSocInfoVO::getEmpId, v -> v, (v1, v2) -> v1));
//        // 公司下员工
//        List<EmpInfoVO> empInfoVOList = empInfoService
//                .selectByCompanyIds(companyIds, yearly, monthly, empStatus, nameOrPhoneOrIdCard, tokenUser);
//        // 未创建月工资但在花名册的员工
//        List<String> addEmpIds = new ArrayList<>();
//        if (!CollectionUtils.isEmpty(empInfoVOList)) {
//            for (EmpInfoVO empInfoVO : empInfoVOList) {
//                // 未创建月工资的员工
//                String empId = empInfoVO.getId();
//                if (!empIds.contains(empId)) {
//                    EmployeeSalaryDO employeeSalaryDO = new EmployeeSalaryDO();
//                    Date parse = DateKit8.parse("1900-01-01", "yyyy-MM-dd");
//                    employeeSalaryDO.setGmtModified(parse);
//                    employeeSalaryDO.setEmpId(empId);
//                    employeeSalaryDOList.add(employeeSalaryDO);
//                    addEmpIds.add(empId);
//                    empIdDoMap.put(empId, empInfoVO.to(EmpInfoDO.class));
//                }
//            }
//        }
//        // 不在职 也未创建月工资 但在参保管理的员工
//        if (!CollectionUtils.isEmpty(empSocInfoVOList)) {
//            for (EmpSocInfoVO empSocInfoVO : empSocInfoVOList) {
//                if (!empIds.contains(empSocInfoVO.getEmpId()) && !addEmpIds.contains(empSocInfoVO.getEmpId())) {
//                    EmployeeSalaryDO employeeSalaryDO = new EmployeeSalaryDO();
//                    Date parse = DateKit8.parse("1900-01-01", "yyyy-MM-dd");
//                    employeeSalaryDO.setGmtModified(parse);
//                    employeeSalaryDO.setEmpId(empSocInfoVO.getEmpId());
//                    employeeSalaryDO.setCompanyId(empSocInfoVO.getCompanyId());
//                    employeeSalaryDOList.add(employeeSalaryDO);
//                }
//            }
//        }
//        return employeeSalaryDOList.parallelStream().map(employeeSalaryDO -> {
//            EmployeeSalaryVO employeeSalaryVO = employeeSalaryDO.to(EmployeeSalaryVO.class);
//            EmpInfoDO empInfoDO = empIdDoMap.get(employeeSalaryDO.getEmpId());
//            // 员工信息
//            if (empInfoDO != null) {
//                employeeSalaryVO.setEmpName(empInfoDO.getName());
//                employeeSalaryVO.setIdCard(empInfoDO.getIdCard());
//                employeeSalaryVO.setEmpStatus(empInfoDO.getStatus());
//                employeeSalaryVO.setCompanyId(empInfoDO.getCompanyId());
//            } else {
//                // 员工不存在 状态为-1
//                employeeSalaryVO.setEmpName("员工已删除");
//                employeeSalaryVO.setEmpStatus(-1);
//            }
//            // 社保信息
//            EmpSocInfoVO empSocInfoVO = empIdEmpSocInfoVoMap.get(employeeSalaryDO.getEmpId());
//            if (empSocInfoVO != null) {
//                employeeSalaryVO.setEmpSocialSecurity(empSocInfoVO.getPersonalSocAmount());
//                employeeSalaryVO.setEmpProvidentFund(empSocInfoVO.getPersonalPfAmount());
//                employeeSalaryVO.setEnterpriseSocialSecurity(empSocInfoVO.getCompanySocAmount());
//                employeeSalaryVO.setEnterpriseProvidentFund(empSocInfoVO.getCompanyPfAmount());
//                // 服务费
//                BigDecimal serviceCharge = employeeSalaryVO.getServiceCharge() == null
//                        ? BigDecimal.ZERO : employeeSalaryVO.getServiceCharge();
//                BigDecimal socServiceCharge = empSocInfoVO.getServiceCharge() == null
//                        ? BigDecimal.ZERO : empSocInfoVO.getServiceCharge();
//                employeeSalaryVO.setServiceCharge(serviceCharge.add(socServiceCharge));
//            }
//            // 员工姓名 手机号 身份证号筛选
//            if (StrKit.isNotEmpty(nameOrPhoneOrIdCard)) {
//                if (!((employeeSalaryVO.getEmpName() != null && employeeSalaryVO.getEmpName().contains(nameOrPhoneOrIdCard))
//                        || (employeeSalaryVO.getPhone() != null && employeeSalaryVO.getPhone().contains(nameOrPhoneOrIdCard))
//                        || (employeeSalaryVO.getIdCard() != null && employeeSalaryVO.getIdCard().contains(nameOrPhoneOrIdCard)))) {
//                    return null;
//                }
//            }
//            if (empStatus != null && !empStatus.equals(employeeSalaryVO.getEmpStatus())) {
//                return null;
//            }
//            return employeeSalaryVO;
//        }).filter(Objects::nonNull).sorted(Comparator.comparing(EmployeeSalaryVO::getEmpStatus).reversed())
//                .sorted(Comparator.comparing(EmployeeSalaryVO::getGmtModified).reversed()).collect(Collectors.toList());
//    }

    @Override
    public String exportExcel(HrEmployeeSalaryQuery hrEmployeeSalaryQuery, TokenUser tokenUser) {
        HashSet<String> totalHeadSet = new HashSet<>();
        // 要导出的数据
        List<EmployeeDetailsVO> employeeDetailsVOList = selectEmployeeSalaryByCompanyIds(hrEmployeeSalaryQuery, tokenUser);
        ParamException.notEmpty(employeeDetailsVOList, "未选择需要导出的数据");

        // 自定义表头
        HeaderFieldsVO headerFieldsVO = selectHeaderDetail(hrEmployeeSalaryQuery.getType(), hrEmployeeSalaryQuery.getId()
                , hrEmployeeSalaryQuery.getCustomerDetailsIdList(), hrEmployeeSalaryQuery.getYearly()
                , hrEmployeeSalaryQuery.getMonthly(), tokenUser);
        ParamException.notNull(headerFieldsVO, "查询表头错误，请刷新后重试");
        List<HeaderFieldsListVO> canSee = headerFieldsVO.getCanSee();
        ParamException.notEmpty(canSee, "无需要导出项，请重新设置表头后导出");

        List<String> fieldNames = canSee.parallelStream().map(HeaderFieldsListVO::getFieldName).parallel().collect(Collectors.toList());
        // 表头
        List<List<String>> headList = new ArrayList<>();
        List<String> oneHead;
        for (String fieldName : fieldNames) {
            // 表头
            oneHead = new ArrayList<>();
            oneHead.add(fieldName);
            headList.add(oneHead);
            // 除姓名、身份证 都需要统计数据
            if (!"姓名".equals(fieldName) && !"身份证号".equals(fieldName) && !"人员状态".equals(fieldName) && !"参保城市".equals(fieldName)) {
                totalHeadSet.add(fieldName);
            }
        }
        // 定义所有的数据集合
        List<List<String>> dataList = new ArrayList<>();
        // 定义每一条数据
        for (EmployeeDetailsVO employeeDetailsVO : employeeDetailsVOList) {
            List<String> oneData = new ArrayList<>();
            // 自定义项
            List<SalaryTemplateItemVO> empItemVOList = JSON.parseArray(
                    employeeDetailsVO.getItemDetail(), SalaryTemplateItemVO.class);
            Map<String, BigDecimal> nameBigDecimalMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(empItemVOList)) {
                // 表头name-金额
                nameBigDecimalMap = empItemVOList.parallelStream().collect(Collectors
                        .toMap(SalaryTemplateItemVO::getName, SalaryTemplateItemVO::getAmount));
            }
            for (String fieldName : fieldNames) {
                if ("姓名".equals(fieldName)) {
                    oneData.add(employeeDetailsVO.getEmpName());
                } else if ("身份证号".equals(fieldName)) {
                    oneData.add(employeeDetailsVO.getIdCard());
                } else if ("应发工资".equals(fieldName)) {
                    oneData.add(BigDecimalKit.nullToString(employeeDetailsVO.getShouldWages()));
                } else if ("个人社保".equals(fieldName)) {
                    oneData.add(BigDecimalKit.nullToString(employeeDetailsVO.getEmpSocialSecurity()));
                } else if ("企业社保".equals(fieldName)) {
                    oneData.add(BigDecimalKit.nullToString(employeeDetailsVO.getEnterpriseSocialSecurity()));
                } else if ("个人公积金".equals(fieldName)) {
                    oneData.add(BigDecimalKit.nullToString(employeeDetailsVO.getEmpProvidentFund()));
                } else if ("企业公积金".equals(fieldName)) {
                    oneData.add(BigDecimalKit.nullToString(employeeDetailsVO.getEnterpriseProvidentFund()));
                } else if ("个人所得税".equals(fieldName)) {
                    oneData.add(BigDecimalKit.nullToString(employeeDetailsVO.getTax()));
                } else if ("实发工资".equals(fieldName)) {
                    oneData.add(BigDecimalKit.nullToString(employeeDetailsVO.getPaidWages()));
                } else if ("服务费".equals(fieldName)) {
                    oneData.add(employeeDetailsVO.getServiceCharge().stripTrailingZeros().toPlainString());
                } else if ("参保城市".equals(fieldName)) {
                    oneData.add(employeeDetailsVO.getSocCityName());
                } else if ("滞纳金".equals(fieldName)) {
                    oneData.add(BigDecimalKit.nullToString(employeeDetailsVO.getFine()));
                } else {
                    oneData.add(BigDecimalKit.nullToString(nameBigDecimalMap.get(fieldName)));
                }
            }
            dataList.add(oneData);
        }
        // 导出excel
        return ExcelKit.exportExcelDynamicAndTotal("empSalary", "客户明细", dataList, headList, totalHeadSet);
    }


    /**
     * 根据员工工资统计得出用工单位级客户结算
     *
     * @param companyId         用工单位Id
     * @param companyName       用工单位名称
     * @param yearly            年
     * @param monthly           月
     * @param customerDetailsDO 客户明细
     * @return 客户结算
     */
    private HrMonthlySalarySummaryVO getHrSummaryVoByCompany(String companyId, String companyName, Integer yearly, Integer monthly
            , CustomerDetailsDO customerDetailsDO) {

        HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO = new HrMonthlySalarySummaryVO();
        // 本月计薪人数
        hrMonthlySalarySummaryVO.setEmpNumber(customerDetailsDO.getEmpNumber());
        // 类型
        String type = customerDetailsDO.getType();
        // 应发
        BigDecimal shouldWages = BigDecimalKit.nullToZero(customerDetailsDO.getShouldWages());
        // 实发
        BigDecimal paidWages = BigDecimalKit.nullToZero(customerDetailsDO.getPaidWages());
        // 企业公积金
        BigDecimal enterpriseProvidentFund = BigDecimalKit.nullToZero(customerDetailsDO.getEnterpriseProvidentFund());
        // 公司社保
        BigDecimal enterpriseSocialSecurity = BigDecimalKit.nullToZero(customerDetailsDO.getEnterpriseSocialSecurity());
        // 服务费
        BigDecimal serviceCharge = BigDecimalKit.nullToZero(customerDetailsDO.getServiceCharge());
        // 滞纳金
        BigDecimal fine = BigDecimalKit.nullToZero(customerDetailsDO.getFine());
        BigDecimal laborCost = customerDetailsDO.getLaborCost();
        // 客户费用
        BigDecimal customerFees = customerDetailsDO.getCustomerFees();
        if (SALARY.getValue().equals(type)) {
            // 薪资明细：本月计薪人数 应发工资 实发工资 服务费 客户费用
            hrMonthlySalarySummaryVO.setShouldWages(shouldWages);
            hrMonthlySalarySummaryVO.setPaidWages(paidWages);
        } else if (SOCIAL.getValue().equals(type)) {
            // 社保明细：本月参保人数 企业社保 企业公积金 服务费 滞纳金 客户费用
            hrMonthlySalarySummaryVO.setEnterpriseProvidentFund(enterpriseProvidentFund);
            hrMonthlySalarySummaryVO.setEnterpriseSocialSecurity(enterpriseSocialSecurity);
            hrMonthlySalarySummaryVO.setFine(fine);
        } else if (CUSTOMER.getValue().equals(type)) {
            // 客户明细：本月人数 应发工资 实发工资 企业社保 企业公积金 服务费 滞纳金 客户费用
            hrMonthlySalarySummaryVO.setShouldWages(shouldWages);
            hrMonthlySalarySummaryVO.setPaidWages(paidWages);
            hrMonthlySalarySummaryVO.setEnterpriseProvidentFund(enterpriseProvidentFund);
            hrMonthlySalarySummaryVO.setEnterpriseSocialSecurity(enterpriseSocialSecurity);
            hrMonthlySalarySummaryVO.setFine(fine);
            hrMonthlySalarySummaryVO.setLaborCost(laborCost);
        }
        // 服务费
        hrMonthlySalarySummaryVO.setServiceCharge(serviceCharge);
        // 客户费用
        hrMonthlySalarySummaryVO.setCustomerFees(customerFees);

        hrMonthlySalarySummaryVO.setName(companyName);
        hrMonthlySalarySummaryVO.setSubjectId(companyId);
        hrMonthlySalarySummaryVO.setPSubjectId("0");
        hrMonthlySalarySummaryVO.setCompanyId(companyId);
        hrMonthlySalarySummaryVO.setCompanyIds(Collections.singletonList(companyId));
        hrMonthlySalarySummaryVO.setCustomerDetailsIds(Collections.singletonList(customerDetailsDO.getId()));
        hrMonthlySalarySummaryVO.setPersonalPeriod(yearly + "年" + monthly + "月");
        hrMonthlySalarySummaryVO.setType("company");

        return hrMonthlySalarySummaryVO;
    }


    /**
     * 根据员工工资统计得出用工单位分组级客户结算
     *
     * @param groupId            用工单位分组Id
     * @param groupName          用工单位分组名称
     * @param yearly             年
     * @param monthly            月
     * @param companySummaryList 用工单位级客户结算
     * @return 客户结算
     */
    private HrMonthlySalarySummaryVO getHrSummaryVoByGroup(String groupId, String groupName, Integer yearly
            , Integer monthly, List<HrMonthlySalarySummaryVO> companySummaryList, Map<String, String> groupIdPidMap) {

        if (CollectionUtils.isEmpty(companySummaryList)) {
            HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO = new HrMonthlySalarySummaryVO();
            hrMonthlySalarySummaryVO.setName(groupName);
            hrMonthlySalarySummaryVO.setSubjectId(groupId);
            hrMonthlySalarySummaryVO.setPSubjectId(groupIdPidMap.get(groupId));
            hrMonthlySalarySummaryVO.setCompanyId(null);
            hrMonthlySalarySummaryVO.setMonthlySalaryId(null);
            hrMonthlySalarySummaryVO.setType("group");
            hrMonthlySalarySummaryVO.setBusinessCost(BigDecimal.ZERO);
            hrMonthlySalarySummaryVO.setCustomerFees(BigDecimal.ZERO);
            hrMonthlySalarySummaryVO.setEmpNumber(0);
            hrMonthlySalarySummaryVO.setEnterpriseProvidentFund(BigDecimal.ZERO);
            hrMonthlySalarySummaryVO.setEnterpriseSocialSecurity(BigDecimal.ZERO);
            hrMonthlySalarySummaryVO.setPaidWages(BigDecimal.ZERO);
            hrMonthlySalarySummaryVO.setPersonalPeriod(yearly
                    + "年" + monthly + "月");
            hrMonthlySalarySummaryVO.setTax(BigDecimal.ZERO);
            hrMonthlySalarySummaryVO.setServiceCharge(BigDecimal.ZERO);
            hrMonthlySalarySummaryVO.setShouldWages(BigDecimal.ZERO);
            hrMonthlySalarySummaryVO.setFine(BigDecimal.ZERO);
            hrMonthlySalarySummaryVO.setLaborCost(BigDecimal.ZERO);
            return hrMonthlySalarySummaryVO;
        }
        BigDecimal businessCost = BigDecimal.ZERO;
        BigDecimal customerFees = BigDecimal.ZERO;
        Integer empNumber = 0;
        BigDecimal enterpriseProvidentFund = BigDecimal.ZERO;
        BigDecimal enterpriseSocialSecurity = BigDecimal.ZERO;
        BigDecimal paidWages = BigDecimal.ZERO;
        BigDecimal tax = BigDecimal.ZERO;
        BigDecimal serviceCharge = BigDecimal.ZERO;
        BigDecimal shouldWages = BigDecimal.ZERO;
        BigDecimal fine = BigDecimal.ZERO;
        BigDecimal laborCost = BigDecimal.ZERO;
        // 用工单位列表
        List<String> companyIds = new ArrayList<>();
        // 客户明细列表
        List<Long> customerDetailsIds = new ArrayList<>();
        for (HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO : companySummaryList) {
            // 分组下公司数值合计
            businessCost = businessCost.add(BigDecimalKit.nullToZero(hrMonthlySalarySummaryVO.getBusinessCost()));
            customerFees = customerFees.add(BigDecimalKit.nullToZero(hrMonthlySalarySummaryVO.getCustomerFees()));
            empNumber += hrMonthlySalarySummaryVO.getEmpNumber();
            enterpriseProvidentFund = enterpriseProvidentFund.add(
                    BigDecimalKit.nullToZero(hrMonthlySalarySummaryVO.getEnterpriseProvidentFund()));
            enterpriseSocialSecurity = enterpriseSocialSecurity.add(
                    BigDecimalKit.nullToZero(hrMonthlySalarySummaryVO.getEnterpriseSocialSecurity()));
            paidWages = paidWages.add(BigDecimalKit.nullToZero(hrMonthlySalarySummaryVO.getPaidWages()));
            tax = tax.add(BigDecimalKit.nullToZero(hrMonthlySalarySummaryVO.getTax()));
            serviceCharge = serviceCharge.add(BigDecimalKit.nullToZero(hrMonthlySalarySummaryVO.getServiceCharge()));
            shouldWages = shouldWages.add(BigDecimalKit.nullToZero(hrMonthlySalarySummaryVO.getShouldWages()));
            fine = fine.add(BigDecimalKit.nullToZero(hrMonthlySalarySummaryVO.getFine()));
            laborCost = laborCost.add(BigDecimalKit.nullToZero(hrMonthlySalarySummaryVO.getLaborCost()));
            companyIds.addAll(hrMonthlySalarySummaryVO.getCompanyIds());
            customerDetailsIds.addAll(hrMonthlySalarySummaryVO.getCustomerDetailsIds());
        }
        HrMonthlySalarySummaryVO hrMonthlySalarySummaryVO = new HrMonthlySalarySummaryVO();
        hrMonthlySalarySummaryVO.setName(groupName);
        hrMonthlySalarySummaryVO.setSubjectId(groupId);
        hrMonthlySalarySummaryVO.setPSubjectId(groupIdPidMap.get(groupId));
        hrMonthlySalarySummaryVO.setCompanyId(null);
        hrMonthlySalarySummaryVO.setMonthlySalaryId(null);
        hrMonthlySalarySummaryVO.setType("group");
        hrMonthlySalarySummaryVO.setBusinessCost(businessCost);
        hrMonthlySalarySummaryVO.setCustomerFees(customerFees);
        hrMonthlySalarySummaryVO.setEmpNumber(empNumber);
        hrMonthlySalarySummaryVO.setEnterpriseProvidentFund(enterpriseProvidentFund);
        hrMonthlySalarySummaryVO.setEnterpriseSocialSecurity(enterpriseSocialSecurity);
        hrMonthlySalarySummaryVO.setPaidWages(paidWages);
        hrMonthlySalarySummaryVO.setPersonalPeriod(yearly
                + "年" + monthly + "月");
        hrMonthlySalarySummaryVO.setTax(tax);
        hrMonthlySalarySummaryVO.setServiceCharge(serviceCharge);
        hrMonthlySalarySummaryVO.setShouldWages(shouldWages);
        hrMonthlySalarySummaryVO.setFine(fine);
        hrMonthlySalarySummaryVO.setLaborCost(laborCost);
        hrMonthlySalarySummaryVO.setHrMonthlySalarySummaryVOList(companySummaryList);
        hrMonthlySalarySummaryVO.setCompanyIds(companyIds);
        hrMonthlySalarySummaryVO.setCustomerDetailsIds(customerDetailsIds);
        return hrMonthlySalarySummaryVO;
    }


    /**
     * 根据查询参数，构建example
     *
     * @param childCompanyQuery 查询参数
     * @param siteId            所属站点id
     * @return example
     */
    private Example buildExample(ChildCompanyQuery childCompanyQuery, String siteId) {
        Example example = new Example(ChildCompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (childCompanyQuery.getName() != null) {
            example.and().andEqualTo("name", childCompanyQuery.getName());
        }
        if (childCompanyQuery.getAddress() != null) {
            example.and().andEqualTo("address", childCompanyQuery.getAddress());
        }
        if (childCompanyQuery.getParentId() != null) {
            example.and().andEqualTo("parentId", childCompanyQuery.getParentId());
        }
        if (childCompanyQuery.getLevel() != null) {
            example.and().andEqualTo("level", childCompanyQuery.getLevel());
        }
        // 排序
        ExampleKit.setExampleOrder(example, childCompanyQuery.getOrders());
        return example;
    }
}




